Garmin inreach API support

This commit is contained in:
Ian Gulliver
2025-08-20 22:42:21 -07:00
parent f84d5db274
commit 1b2fe81f50
2 changed files with 133 additions and 11 deletions

87
garmin.go Normal file
View File

@@ -0,0 +1,87 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
type garminClient struct {
c *http.Client
apiKey string
}
type garminMessageRequest struct {
Messages []garminMessage `json:"messages"`
}
type garminMessage struct {
Recipients []string `json:"recipients"`
Sender string `json:"sender"`
Timestamp string `json:"timestamp"`
Message string `json:"message"`
}
type garminMessageResponse struct {
Count int `json:"count"`
}
func newGarminClient(apiKey string) *garminClient {
return &garminClient{
c: &http.Client{},
apiKey: apiKey,
}
}
func (gc *garminClient) sendMessage(imei, sender, msg string) error {
buf := &bytes.Buffer{}
err := json.NewEncoder(buf).Encode(garminMessageRequest{
Messages: []garminMessage{
{
Recipients: []string{imei},
Sender: sender,
Timestamp: time.Now().Format(time.RFC3339),
Message: msg,
},
},
})
if err != nil {
return err
}
req, err := http.NewRequest("POST", "https://ipcinbound.inreachapp.com/IPC/IPCInboundApi/api/Messaging/Message", buf)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("x-api-key", gc.apiKey)
resp, err := gc.c.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != 200 {
return fmt.Errorf("%s", string(body))
}
grResp := garminMessageResponse{}
err = json.NewDecoder(resp.Body).Decode(&grResp)
if err != nil {
return err
}
if grResp.Count != 1 {
return fmt.Errorf("expected 1 message, got %d", grResp.Count)
}
return nil
}

47
main.go
View File

@@ -12,10 +12,13 @@ import (
type PHandler struct { type PHandler struct {
tmpl *template.Template tmpl *template.Template
pd *pdClient pd *pdClient
gc *garminClient
garminIMEI string
garminSender string
mux *http.ServeMux mux *http.ServeMux
} }
func NewPHandler(routingKey string) (*PHandler, error) { func NewPHandler(pdRoutingKey, garminApiKey, garminIMEI, garminSender string) (*PHandler, error) {
tmpl := template.New("index.html") tmpl := template.New("index.html")
tmpl.Funcs(template.FuncMap{ tmpl.Funcs(template.FuncMap{
@@ -29,7 +32,10 @@ func NewPHandler(routingKey string) (*PHandler, error) {
ph := &PHandler{ ph := &PHandler{
tmpl: tmpl, tmpl: tmpl,
pd: newPDClient(routingKey), pd: newPDClient(pdRoutingKey),
gc: newGarminClient(garminApiKey),
garminIMEI: garminIMEI,
garminSender: garminSender,
mux: http.NewServeMux(), mux: http.NewServeMux(),
} }
@@ -62,7 +68,7 @@ func (ph *PHandler) serveRoot(w http.ResponseWriter, r *http.Request) {
return return
} }
err = ph.pd.sendAlert(m) err = ph.sendAlert(m)
if err != nil { if err != nil {
sendError(w, http.StatusInternalServerError, "Error sending to PagerDuty: %s", err) sendError(w, http.StatusInternalServerError, "Error sending to PagerDuty: %s", err)
return return
@@ -70,6 +76,20 @@ func (ph *PHandler) serveRoot(w http.ResponseWriter, r *http.Request) {
sendResponse(w, "Page sent") sendResponse(w, "Page sent")
} }
func (ph *PHandler) sendAlert(m string) error {
err := ph.pd.sendAlert(m)
if err != nil {
return fmt.Errorf("Error sending to PagerDuty: %s", err)
}
err = ph.gc.sendMessage(ph.garminIMEI, ph.garminSender, m)
if err != nil {
return fmt.Errorf("Error sending to Garmin: %s", err)
}
return nil
}
var allowedEnvs = []string{ var allowedEnvs = []string{
"SHORT_NAME", "SHORT_NAME",
"CONTACT_NAME", "CONTACT_NAME",
@@ -94,12 +114,27 @@ func (ph *PHandler) envs() map[string]string {
} }
func main() { func main() {
routingKey := os.Getenv("PD_ROUTING_KEY") pdRoutingKey := os.Getenv("PD_ROUTING_KEY")
if routingKey == "" { if pdRoutingKey == "" {
log.Fatalf("please set PD_ROUTING_KEY") log.Fatalf("please set PD_ROUTING_KEY")
} }
ph, err := NewPHandler(routingKey) garminApiKey := os.Getenv("GARMIN_API_KEY")
if garminApiKey == "" {
log.Fatalf("please set GARMIN_API_KEY")
}
garminIMEI := os.Getenv("GARMIN_IMEI")
if garminIMEI == "" {
log.Fatalf("please set GARMIN_IMEI")
}
garminSender := os.Getenv("GARMIN_SENDER")
if garminSender == "" {
log.Fatalf("please set GARMIN_SENDER")
}
ph, err := NewPHandler(pdRoutingKey, garminApiKey, garminIMEI, garminSender)
if err != nil { if err != nil {
log.Fatalf("NewPHandler: %s", err) log.Fatalf("NewPHandler: %s", err)
} }