Skip to content

Commit

Permalink
bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
brchri committed Dec 30, 2023
1 parent 3d92f80 commit 9581ce1
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 20 deletions.
26 changes: 22 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ A lightweight app that will operate your smart Garage Door Openers (GDOs) based

- [Tesla-GeoGDO](#tesla-geogdo)
- [Supported Smart Garage Door Openers](#supported-smart-garage-door-openers)
- [Current](#current)
- [Deprecated:](#deprecated)
- [Potentially Upcoming](#potentially-upcoming)
- [Prerequisite](#prerequisite)
- [How to use](#how-to-use)
- [How to Use](#how-to-use)
- [Docker](#docker)
- [Supported Environment Variables](#supported-environment-variables)
- [API](#api)
- [Notes](#notes)
- [Geofence Types](#geofence-types)
- [Circular Geofence](#circular-geofence)
- [TeslaMate Defined Geofence](#teslamate-defined-geofence)
- [Polygon Geofence](#polygon-geofence)
- [Operation Cooldown](#operation-cooldown)
- [Credits](#credits)

Expand Down Expand Up @@ -50,6 +51,7 @@ This app is provided as a docker image. You will need to create a `config.yml` f
docker run \
-e TZ=America/New_York \
-v /etc/tesla-geogdo:/app/config \
-p 8555:8555 \
brchri/tesla-geogdo:latest
```

Expand All @@ -63,6 +65,8 @@ services:
container_name: tesla-geogdo
environment:
- TZ=America/New_York # optional, sets timezone for container
ports:
- 8555:8555 # optional, only needed to use api
volumes:
- /etc/tesla-geogdo:/app/config # required, mounts folder containing config file(s) into container
restart: unless-stopped
Expand All @@ -79,6 +83,20 @@ The following Docker environment variables are supported but not required.
| `TESTING` | Bool | Will perform all functions *except* actually operating garage door, and will just output operation *would've* happened |
| `TZ` | String | Sets timezone for container |

### API
There is a very simple API available that will allow you limited control of Tesla-GeoGDO remotely. To use it, you must expose a port mapping to port 8555 in the container (see the docker run and docker compose examples above). There are currently two endpoints available:

* `GET /pause`
* Pauses garage operations. Takes an optional `duration` parameter to define how long garage operations should be paused, in seconds
* Can override previous pause command (e.g. increase the remaining time of a pause command currently in effect)
* Examples:
* `curl http://geogdo-ip:8555/pause?duration=10` (pauses garage operations for 10 seconds)
* `curl http://geogdo-ip:8555/pause` (pauses garage operations indefinitely)
* `GET /resume`
* Resumes garage operations if they are currently paused; otherwise has no effect
* Example:
* `curl http://geogdo-ip:8555/resume`

## Notes
### Geofence Types
You can define 3 different types of geofences to trigger garage operations. You must configure *one and only one* geofence type for each garage door. Each geofence type has separate `open` and `close` configurations (though they can be set to the same values). This is useful for situations where you might want a smaller geofence that closes the door so you can visually confirm it's closing, but you want a larger geofence that opens the door so it will start sooner and be fully opened when you actually arrive.
Expand Down
39 changes: 26 additions & 13 deletions cmd/app/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func main() {
pauseChan = make(chan int)
http.HandleFunc("/pause", apiPauseHandler)
http.HandleFunc("/resume", apiPauseHandler)
http.ListenAndServe(":8555", nil)
go http.ListenAndServe(":8555", nil)

messageChan = make(chan mqtt.Message)

Expand Down Expand Up @@ -363,38 +363,51 @@ func apiPauseHandler(w http.ResponseWriter, r *http.Request) {
}

func pauseOperations(duration int) {
logger.Infof("Received request to pause operations, pausing for %d seconds", duration)
if util.Config.MasterOpLock {
if duration == 0 {
duration = -1 // if no duration was defined, set to -1 for infinite pause
}
if duration > 0 {
logger.Infof("Received request to pause operations, pausing for %d seconds, use /resume endpoint to resume garage operations sooner than indicated time", duration)
} else {
logger.Info("Received request to pause operations indefinitely; use /resume endpoint to resume garage operations")
}

if util.Config.MasterOpLock > 0 { // if we have a finite lock in progress, send new duration to channel
pauseChan <- duration
return
}
util.Config.MasterOpLock = true
if duration > 0 {
util.Config.MasterOpLock = duration

// only set a timeout loop if duration > 0, negatives are infinite pauses
if util.Config.MasterOpLock > 0 {
go func() {
for ; duration > 0; duration-- {
for ; util.Config.MasterOpLock > 0; util.Config.MasterOpLock-- {
time.Sleep(1 * time.Second)

// non-blocking select to check for channel message indicating a resume api call has been made and we can break the loop
select {
case msg := <-pauseChan:
if msg > 0 {
duration = msg
} else {
util.Config.MasterOpLock = msg
if msg <= 0 {
// either received an indefinite pause (<0) or a resume (=0), so loop with unlock final action is no longer needed
return
}
default:
}
}
logger.Debug("Pause duration reached; unpausing operation")
util.Config.MasterOpLock = false
util.Config.MasterOpLock = 0
}()
}
}

func resumeOperations() {
logger.Info("Received request to resume operations")
if util.Config.MasterOpLock {
pauseChan <- 0 // send signal to pause timeout loop it's no longer needed
util.Config.MasterOpLock = false
if util.Config.MasterOpLock > 0 {
// send signal to pause timeout loop it's no longer needed
// send as goroutine as we only read channel every 1 second, so this ensures fast api response while waiting for channel to be read by loop
go func() { pauseChan <- 0 }()
} else if util.Config.MasterOpLock < 0 {
util.Config.MasterOpLock = 0 // override indefinite pause
}
}
4 changes: 2 additions & 2 deletions internal/geo/geo.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ func CheckGeofence(tracker *Tracker) {
if action == "" {
return // nothing to do
}
if util.Config.MasterOpLock {
logger.Warnf("Garage operations are currently paused due to user request, will not execute action '%s'", action)
if util.Config.MasterOpLock != 0 {
logger.Warnf("Garage operations are currently paused due to user request, will not execute action '%s'. Use /resume api endpoint to resume garage operations", action)
return
}
if tracker.GarageDoor.OpLock {
Expand Down
2 changes: 1 addition & 1 deletion internal/util/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type (
} `yaml:"global"`
GarageDoors []*map[string]interface{} `yaml:"garage_doors"` // this will be parsed properly later by the geo package
Testing bool
MasterOpLock bool
MasterOpLock int // user-initiated lock (pause), values: 0 = disabled, <0 = indefinite pause, >0 = num seconds left on finite timeout
}

MqttConnectSettings struct {
Expand Down

0 comments on commit 9581ce1

Please sign in to comment.