Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade example container to use Partner api v3 #7

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
upgrade to partner api v3
  • Loading branch information
wei-huang-aruba committed Sep 23, 2024
commit cabced4b3f795be0e95c13b3e9f6c6e51785455f
37 changes: 0 additions & 37 deletions container/application/ble_data.go

This file was deleted.

52 changes: 30 additions & 22 deletions container/application/http_client.go
Original file line number Diff line number Diff line change
@@ -19,7 +19,6 @@ import (
"encoding/json"
"log"
"net/http"
"strings"
"time"
)

@@ -70,7 +69,7 @@ func (c *HTTPClient) Connect(ctx context.Context) {
return
}

reader := bufio.NewReader(resp.Body)
scanner := bufio.NewScanner(resp.Body)

go func() {
defer func() {
@@ -79,32 +78,41 @@ func (c *HTTPClient) Connect(ctx context.Context) {
}
}()

for {
line, err := reader.ReadBytes('\n')
if err != nil {
log.Println(err.Error())

return
}

if len(line) > 0 {
// the structure of data is : `data:{"key":"value"}`
// below code will replace `data:` with "", leaving only json structured data.
if strings.Contains(string(line), "data:") {
str := strings.ReplaceAll(string(line), "data:", "")
str = strings.ReplaceAll(str, "\n", "")

bleData := &BleData{}
_ = json.Unmarshal([]byte(str), bleData)

c.dataCh <- bleData
}
for scanner.Scan() {
//log.Println(scanner.Text())
bleData := bleDataFromResult(scanner.Bytes())
if bleData != nil {
c.dataCh <- bleData
}
}
if err := scanner.Err(); err != nil {
log.Println(err.Error())
}
}()
}

func bleDataFromResult(aResult []byte) *BleData {
bleData := new(BleData)
err := json.Unmarshal(aResult, bleData)
if err != nil {
return nil
}
return bleData
}

// GetDataCh returns the streaming ble data channel
func (c *HTTPClient) GetDataCh() <-chan *BleData {
return c.dataCh
}

type BleData struct {
Result struct {
Mac string `json:"mac"`
ApMac string `json:"apMac"`
Payload []byte `json:"payload"`
Rssi int `json:"rssi"`
FrameType string `json:"frameType"`
RadioMac string `json:"radioMac"`
MacAddressType string `json:"macAddressType"`
} `json:"result"`
}
21 changes: 15 additions & 6 deletions container/application/main.go
Original file line number Diff line number Diff line change
@@ -45,7 +45,7 @@ func main() {
mqttClient.Connect()

// bleAPIURL: example app will get data from HPE IoT Operations infrastructure services through this API url
bleAPIURL := "http://" + apiGwURL + "/api/v2/ble/stream/packets"
bleAPIURL := "http://" + apiGwURL + "/api/v3/ble/stream/packets"
httpClient := NewHTTPClient(bleAPIURL, apiKey, http.MethodGet)
httpClient.Connect(context.Background())

@@ -54,12 +54,21 @@ func main() {

const minBleDataLen = 30

type IBeaconData struct {
DeviceClass string
UUID string
Major string
Minor string
Power string
}

// ProcessBleData get data from HPE IoT Operations infrastructure service.
// then decode and decorate and put data into data channel,
// data channel will be consumed by MQTT client.
func ProcessBleData(httpDataCh <-chan *BleData, mqttDataCh chan<- string) {
for bleData := range httpDataCh {
if len(bleData.Data) < minBleDataLen {
payload := bleData.Result.Payload
if len(payload) < minBleDataLen {
continue
}

@@ -69,10 +78,10 @@ func ProcessBleData(httpDataCh <-chan *BleData, mqttDataCh chan<- string) {
// If you want to get string data. please process it with method hex.EncodeToString([]byte)
iBeaconData := &IBeaconData{
DeviceClass: "iBeacon",
UUID: hex.EncodeToString(bleData.Data[9:25]),
Major: hex.EncodeToString(bleData.Data[25:27]),
Minor: hex.EncodeToString(bleData.Data[27:29]),
Power: hex.EncodeToString(bleData.Data[29:30]),
UUID: hex.EncodeToString(payload[9:25]),
Major: hex.EncodeToString(payload[25:27]),
Minor: hex.EncodeToString(payload[27:29]),
Power: hex.EncodeToString(payload[29:30]),
}
iBeacon, _ := json.Marshal(iBeaconData)

72 changes: 25 additions & 47 deletions container/application/main_test.go
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ package main

import (
"context"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
@@ -26,71 +27,48 @@ import (
"time"
)

func TestExampleApp(t *testing.T) {
t.Parallel()

tests := []struct {
name string
}{
{name: "SE request"},
}

for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
const iBeaconRawHex = "0201041AFF4C000215F7826DA64FA24E988024BC5B71E0893E00000000C5"

server := SEServerMock()
func TestExampleApp(t *testing.T) {
server := SEServerMock()

// http client
log.Println("Request Ble data and transfer it to a third party server")
// http client
log.Println("Request Ble data and transfer it to a third party server")

BleRequestURL := server.URL + "/api/v2/ble/stream/packets"
httpClient := NewHTTPClient(BleRequestURL, "", http.MethodGet)
httpClient.Connect(context.Background())
BleRequestURL := server.URL + "/api/v3/ble/stream/packets"
httpClient := NewHTTPClient(BleRequestURL, "", http.MethodGet)
httpClient.Connect(context.Background())

mqttDataCh := make(chan string, 1)
mqttDataCh := make(chan string, 1)

// bleClient process ble data
go ProcessBleData(httpClient.GetDataCh(), mqttDataCh)
// bleClient process ble data
go ProcessBleData(httpClient.GetDataCh(), mqttDataCh)

iBeaconData := &IBeaconData{}
iBeaconData := &IBeaconData{}

go func() {
result := <-mqttDataCh
_ = json.Unmarshal([]byte(result), iBeaconData)
}()
go func() {
result := <-mqttDataCh
_ = json.Unmarshal([]byte(result), iBeaconData)
}()

<-time.After(20 * time.Millisecond)
<-time.After(20 * time.Millisecond)

if strings.ToUpper(iBeaconData.UUID) != "F7826DA64FA24E988024BC5B71E0893E" {
t.Error("Get iBeacon data failed")
}
})
if strings.ToUpper(iBeaconData.UUID) != iBeaconRawHex[18:50] {
t.Error("Get iBeacon data failed")
}
}

func SEServerMock() *httptest.Server {
log.Println("start HTTP server. send Ble data to client.")
// mock data
var frameType BleFrameType = 3

bleDataMock, _ := hex.DecodeString("0201041AFF4C000215F7826DA64FA24E988024BC5B71E0893E00000000C5")
bleDataMock, _ := hex.DecodeString(iBeaconRawHex)
payload := base64.StdEncoding.EncodeToString(bleDataMock)

// ble structure: 0201041AFF 4C00 02 15 4152554EF94A3B869470706978210A00(UUID) 0000(Major) 0000(Minor) C8(power)
bleData := &BleData{
Mac: "50:31:ad:02:5c:93",
Data: bleDataMock,
Rssi: -57,
FrameType: &frameType,
ApMac: "11:22:33:44:55:66",
}
bleDataJSON, _ := json.Marshal(bleData)
testData := "data:" + string(bleDataJSON) + "\n"
testData := fmt.Sprintf(`{"result":{"mac":"dc:a6:32:3f:1f:33","apMac":"ff:ff:2c:5d:94:9f","payload":"%s","rssi":-46,"frameType":"BLE_FRAME_TYPE_ADV_IND","radioMac":"ff:11:df:f5:ba:b1","macAddressType":"BLE_MAC_ADDRESS_TYPE_PUBLIC"}}`, payload)

// HTTP server
server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
if request.URL.EscapedPath() != "/api/v2/ble/stream/packets" {
if request.URL.EscapedPath() != "/api/v3/ble/stream/packets" {
_, _ = fmt.Fprintf(writer, "Reqeust path error")
}
if request.Method != http.MethodGet {
@@ -99,7 +77,7 @@ func SEServerMock() *httptest.Server {

flusher, _ := writer.(http.Flusher)

_, _ = fmt.Fprint(writer, testData)
writer.Write(append([]byte(testData), []byte("\n")...))
flusher.Flush()

time.Sleep(1 * time.Second)