Skip to content

Creating an IOS shortcut to open my door with Golang and Vercel

Posted on:February 27, 2023 at 07:00 PM

1. Introduction

My apartment building is using an automated system to unlock the front door. We have to use a proprietary app (AlphaTouch) and unlock the door by sliding a toggle. It takes time because the app is slow. Let’s find a way to make this easier!

Goal

Let’s have an iOS Shortcut instead! I will just have to press it on my phone home page. It’s possible to create a Shortcut that execute a http request
I would like to have a simple endpoint (http://myendpoint.something/unlock_door)

2. Let’s find a way to open my door without the App

Alphatouch provides an APP and a Website. When we open the website, we can see a “Trigger Open Door” button. Let’s click on it and check the network calls open door network calls

We can see that clicking this button fire a network call that I suppose open the door (the url is .../trigger_pin.php)

Before going further, let’s copy this command call as cURL (using the DevTools again) and let’s fire this CURL call again while I am in front of my door.
Success! The door open!

This network call contains tons of headers + query params + a body. We could just fire it from our iOS shortcut, but let’s make things easier and play with serverless functions instead!

3. A Go program triggering our cURL code

I chose to use Go because this is what I am using every day. We could use Python or JS, both are supported by serverless functions and may be faster to write, but I like Go syntax.

Let’s create a new folder/repository for our program. First, we need a simple function that triggers our http call.

To convert our complex cURL call to Go code, we can use this website: https://mholt.github.io/curl-to-go/

internal/open_door_entry/open_door.go
package open_door_entry
 
import (
	"encoding/json"
	"errors"
	"io"
	"net/http"
	"strings"
)
 
// By looking at the response from the HTTP Call, we can see that we get a JSON object contain a "success" variable
// Let's declare this object in Go in order to parse the reponse and monitor error/success
// It's easy to do with Jetbrains IDE, especially Goland. You can do "CMD+N" and "Type from JSON"
type openDoorResponse struct {
	Success bool `json:"success"`
}
 
func createReq() (*http.Request, error) {
    // generate this code using https://mholt.github.io/curl-to-go/
	req, err := ...
	return req, nil
}
 
// the function that will open our Door.
func OpenDoor() error {
	req, err := createReq()
	if err != nil {
		return err
	}
 
    // let's execute the query
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	
	if resp.StatusCode != 200 {
		return errors.New(resp.Status)
	}
	
	
	// reading the body...
	defer resp.Body.Close()
	b, err := io.ReadAll(resp.Body)
	if err != nil {
		return err
	}
 
	// parsing the body
	var openDoorResp openDoorResponse
	err = json.Unmarshal(b, &openDoorResp)
	if err != nil {
		return err
	}
 
    // Checking response success
	if openDoorResp.Success {
		return nil
	}
	return errors.New("error success=false from response")
}
 

4. Let’s deploy this to Vercel

This piece of code is very small and fast to execute (~1sec, most of the time is spent in the http call) I plan to trigger this ~5 times a day (everytime I want to open my front door).

I found that the cheapest way to host this is to use serverless tech.
There are multiple offerings here, the most popular are:

I heard good things about Vercel and I wanted to try them for a while. They are supposed to deliver the best dev experience.

Let’s try this out!
After looking at their website, they offer Serverless Functions. As a part of their Free plan, you have access to:

That’s perfect for our use case! Let’s set this up.

Every function with a specific signature in this folder will be a Serverless Function. Let’s create ours!

// api/open_door.go
package handler
 
import (
	"net/http"
 
    // the func we just made before
	"dimitriwyzlic.com/serverless_functions/internal/open_door_entry"
)
 
// Any function using this signature will be a Serverless Func
func OpenDoor(w http.ResponseWriter, r *http.Request) {
	err := open_door_entry.OpenDoor()
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte(err.Error()))
	} else {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("Success!"))
	}
}

vercel logs

5. Conclusion

Congratulation! You now have a working Go function hosted on the cloud that should be free forever!

I wanted to have an iOS shortcut that will allow me to open my door. The last step is just to create a shortcut with the Open URL or Get contents of action!