Skip to content

Commit

Permalink
Add support for H200 hub and child devices (for example battery power…
Browse files Browse the repository at this point in the history
…ed doorbell D230S1)
  • Loading branch information
aprilmaccydee committed Apr 1, 2024
1 parent 5fa31fe commit 801bb2d
Showing 1 changed file with 33 additions and 6 deletions.
39 changes: 33 additions & 6 deletions pkg/tapo/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ func (c *Client) newConn() (net.Conn, error) {
return nil, err
}

query := u.Query()

deviceId := query.Get("deviceId")
if deviceId != "" {
q := req.URL.Query()
q.Set("deviceId", deviceId)
req.URL.RawQuery = q.Encode()
}

req.URL.User = u.User
req.Header.Set("Content-Type", "multipart/mixed; boundary=--client-stream-boundary--")

Expand All @@ -91,7 +100,6 @@ func (c *Client) newConn() (net.Conn, error) {
c.newDectypter(res)
}

query := u.Query()
channel := query.Get("channel")
if channel == "" {
channel = "0"
Expand Down Expand Up @@ -284,6 +292,9 @@ func dial(req *http.Request) (net.Conn, *http.Response, error) {
return nil, nil, err
}

// Read the entire request body to prevent issues later - H200 seems to send HTTP ERROR 401 as body response.
_, _ = io.Copy(io.Discard, res.Body)

if password == "" {
// support cloud password in place of username
if strings.Contains(auth, `encrypt_type="3"`) {
Expand All @@ -297,17 +308,33 @@ func dial(req *http.Request) (net.Conn, *http.Response, error) {
realm := tcp.Between(auth, `realm="`, `"`)
nonce := tcp.Between(auth, `nonce="`, `"`)
qop := tcp.Between(auth, `qop="`, `"`)
// opaque is optional
op := ""
if strings.Contains(auth, `opaque="`) {
op = tcp.Between(auth, `opaque="`, `"`)
}
uri := req.URL.RequestURI()
ha1 := tcp.HexMD5(username, realm, password)
ha2 := tcp.HexMD5(req.Method, uri)
nc := "00000001"
cnonce := "00000001"

// Generate a random cnonce
cnonce := core.RandString(32, 64)

response := tcp.HexMD5(ha1, nonce, nc, cnonce, qop, ha2)

header := fmt.Sprintf(
`Digest username="%s", realm="%s", nonce="%s", uri="%s", qop=%s, nc=%s, cnonce="%s", response="%s"`,
username, realm, nonce, uri, qop, nc, cnonce, response,
)
header := ""
if op != "" {
header = fmt.Sprintf(
`Digest username="%s", realm="%s", nonce="%s", uri="%s", qop=%s, nc=%s, cnonce="%s", response="%s", opaque="%s", algorithm=MD5`,
username, realm, nonce, uri, qop, nc, cnonce, response, op,
)
} else {
header = fmt.Sprintf(
`Digest username="%s", realm="%s", nonce="%s", uri="%s", qop=%s, nc=%s, cnonce="%s", response="%s"`,
username, realm, nonce, uri, qop, nc, cnonce, response,
)
}

req.Header.Set("Authorization", header)

Expand Down

0 comments on commit 801bb2d

Please sign in to comment.