Skip to content

Commit

Permalink
use http and add tests for http
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnN193 committed Feb 14, 2025
1 parent 072fbd2 commit d3e09c5
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 16 deletions.
18 changes: 12 additions & 6 deletions draginolht65n/sensor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ package draginolht65n

import (
"context"
"embed"
"net/http"
"time"

"github.com/viam-modules/gateway/node"
"go.viam.com/rdk/components/sensor"
"go.viam.com/rdk/logging"
"go.viam.com/rdk/resource"
)

//go:embed LHT65NChirpstack4decoder.js
var decoderFile embed.FS

const decoderFilename = "LHT65NChirpstack4decoder.js"
const (
decoderFilename = "LHT65NChirpstack4decoder.js"
decoderURL = "https://raw.githubusercontent.com/dragino/dragino-end-node-decoder/refs/heads/main/LHT65N/" +
"LHT65N Chirpstack 4.0 decoder.txt"
)

// Model represents a dragino-LHT65N lorawan node model.
var Model = resource.NewModel("viam", "lorawan", "dragino-LHT65N")
Expand Down Expand Up @@ -79,10 +81,14 @@ func newLHT65N(
conf resource.Config,
logger logging.Logger,
) (sensor.Sensor, error) {
decoderFilePath, err := node.WriteDecoderFile(decoderFilename, decoderFile)
httpClient := &http.Client{
Timeout: time.Second * 25,
}
decoderFilePath, err := node.WriteDecoderFileFromURL(ctx, decoderFilename, decoderURL, httpClient, logger)
if err != nil {
return nil, err
}

n := &LHT65N{
Named: conf.ResourceName().AsNamed(),
logger: logger,
Expand Down
2 changes: 2 additions & 0 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ var (
ErrNwkSKeyLength = errors.New("network session key must be 16 bytes")
ErrDevAddrRequired = errors.New("device address is required for ABP join type")
ErrDevAddrLength = errors.New("device address must be 4 bytes")
ErrBadDecoderURL = "Error Retreiving decoder url is invalid, please report to maintainer: " +
"Status Code %v"
)

const (
Expand Down
88 changes: 88 additions & 0 deletions node/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ package node
import (
"context"
"encoding/hex"
"fmt"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"

"go.viam.com/rdk/components/encoder"
"go.viam.com/rdk/data"
Expand Down Expand Up @@ -356,3 +361,86 @@ func TestReadings(t *testing.T) {
test.That(t, err, test.ShouldBeNil)
test.That(t, readings, test.ShouldResemble, noReadings)
}

type ctrl struct {
statusCode int
response string
}

func (c *ctrl) mockHandler(w http.ResponseWriter, r *http.Request) {
resp := []byte(c.response)

w.WriteHeader(c.statusCode)
w.Write(resp)
}

// HTTPMock creates a mock HTTP server.
func HTTPMock(pattern string, statusCode int, response string) *httptest.Server {
c := &ctrl{statusCode, response}

handler := http.NewServeMux()
handler.HandleFunc(pattern, c.mockHandler)

return httptest.NewServer(handler)
}

func TestWriteDecoder(t *testing.T) {
logger := logging.NewTestLogger(t)
// Prep first run directory
dataDirectory1 := t.TempDir()

t.Setenv("VIAM_MODULE_DATA", dataDirectory1)

t.Run("Test successful request of decoder", func(t *testing.T) {
resp := "good test"
srv := HTTPMock("/myurl", http.StatusOK, resp)
sClient := &http.Client{
Timeout: time.Second * 180,
}
decoderName1 := "decoder1.js"

fileName1, err := WriteDecoderFileFromURL(context.Background(), decoderName1, srv.URL+"/myurl", sClient, logger)
test.That(t, err, test.ShouldBeNil)
test.That(t, fileName1, test.ShouldContainSubstring, decoderName1)
file1, err := os.ReadFile(fileName1)
test.That(t, err, test.ShouldBeNil)
test.That(t, string(file1), test.ShouldEqual, resp)
// second decoder

resp2 := "good test 2"
srv2 := HTTPMock("/myurl", http.StatusOK, resp2)
sClient2 := &http.Client{
Timeout: time.Second * 180,
}
decoderName2 := "decoder2.js"

fileName2, err := WriteDecoderFileFromURL(context.Background(), decoderName2, srv2.URL+"/myurl", sClient2, logger)
test.That(t, err, test.ShouldBeNil)
test.That(t, fileName2, test.ShouldContainSubstring, decoderName2)
file2, err := os.ReadFile(fileName2)
test.That(t, err, test.ShouldBeNil)
test.That(t, string(file2), test.ShouldEqual, resp2)
dirEntries, err := os.ReadDir(dataDirectory1)
test.That(t, err, test.ShouldBeNil)
test.That(t, len(dirEntries), test.ShouldEqual, 2)

// repeat decoder
_, err = WriteDecoderFileFromURL(context.Background(), decoderName1, srv.URL+"/myurl", sClient, logger)
test.That(t, err, test.ShouldBeNil)
dirEntries, err = os.ReadDir(dataDirectory1)
test.That(t, err, test.ShouldBeNil)
test.That(t, len(dirEntries), test.ShouldEqual, 2)
})

t.Run("Test failed request of decoder", func(t *testing.T) {
resp := "bad test"
srv := HTTPMock("/myurl", http.StatusNotFound, resp)
sClient := &http.Client{
Timeout: time.Second * 180,
}
decoderBad := "decoder3.js"

_, err := WriteDecoderFileFromURL(context.Background(), decoderBad, srv.URL+"/myurl", sClient, logger)
test.That(t, err, test.ShouldBeError, fmt.Errorf(ErrBadDecoderURL, 404))
})
}
16 changes: 6 additions & 10 deletions node/node_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"embed"
"encoding/hex"
"errors"
"fmt"
"io"
"net/http"
"os"
Expand Down Expand Up @@ -157,10 +158,8 @@ func WriteDecoderFile(decoderFilename string, decoderFile embed.FS) (string, err
return filePath, nil
}

// GetFileFromURL writes a decoder file from a url into the data folder of the module.
func GetFileFromURL(ctx context.Context, decoderFilename, url string, logger logging.Logger) (string, error) {
url = "https://raw.githubusercontent.com/dragino/dragino-end-node-decoder/refs/heads/main/LHT65N/LHT65N Chirpstack 4.0 decoder.txt"

// WriteDecoderFileFromURL writes a decoder file from a url into the data folder of the module.
func WriteDecoderFileFromURL(ctx context.Context, decoderFilename, url string, httpClient *http.Client, logger logging.Logger) (string, error) {
moduleDataDir := os.Getenv("VIAM_MODULE_DATA")
filePath := filepath.Join(moduleDataDir, decoderFilename)

Expand All @@ -174,17 +173,13 @@ func GetFileFromURL(ctx context.Context, decoderFilename, url string, logger log
return "", err
}

logger.Info("Getting decoder")
httpClient := &http.Client{
Timeout: time.Second * 25,
}
res, err := httpClient.Do(req)
if err != nil {
return "", err
}
// check that the request was successful.
if res.StatusCode != http.StatusOK {
return "", err
return "", fmt.Errorf(ErrBadDecoderURL, res.StatusCode)
}
// get the decoder data.
decoderData, err := io.ReadAll(res.Body)
Expand All @@ -193,7 +188,8 @@ func GetFileFromURL(ctx context.Context, decoderFilename, url string, logger log
}
//nolint:errcheck
defer res.Body.Close()
logger.Infof("Writing decoder to file %s", filePath)

logger.Debugf("Writing decoder to file %s", filePath)
//nolint:all
err = os.WriteFile(filePath, decoderData, 0755)
if err != nil {
Expand Down

0 comments on commit d3e09c5

Please sign in to comment.