From b08cb70174ce25246ebdb3ee0a547ccd248631b9 Mon Sep 17 00:00:00 2001 From: F4310sp Date: Fri, 20 Sep 2024 21:28:30 -0300 Subject: [PATCH 01/25] DisplayImage Function --- chipper/pkg/wirepod/sdkapp/server.go | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index 884bae6b..1c932280 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -140,6 +140,40 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte(json)) return } + case r.URL.Path == "/api-sdk/display_image": + + r.ParseMultipartForm(2 << 20) + imgPath, _, err := r.FormFile("image") + + // Lê a imagem e trata possíveis erros + faceBytes, err := io.ReadAll(imgPath) + if err != nil { + http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) + return + } + + ctx := r.Context() + ctx, cancel := context.WithTimeout(ctx, 15*time.Second) + defer cancel() + + // Defina a duração e o bloqueio + duration := 3000 // Duração em milissegundos + + // Chamada da função DisplayFaceImageRGB e tratamento de erro + resp, err := robot.Conn.DisplayFaceImageRGB(ctx, &vectorpb.DisplayFaceImageRGBRequest{ + FaceData: faceBytes, // Certifique-se de que este campo é exportado + DurationMs: uint32(duration), // Certifique-se de que este campo é exportado + InterruptRunning: true, // Certifique-se de que este campo é exportado + }) + if err != nil { + http.Error(w, "Error displaying face image: "+err.Error(), http.StatusInternalServerError) + return + } + + // Responda com um status de sucesso + fmt.Fprintf(w, "Face image displayed successfully: %+v", resp) + return + case r.URL.Path == "/api-sdk/get_battery": // Ensure the endpoint times out after 15 seconds ctx := r.Context() // Get the request context From fd56ce6d8f7b9edbf4faeeb3c84ed713e6cf45ab Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 18:40:42 -0300 Subject: [PATCH 02/25] Added Function RGB to bytes --- chipper/pkg/wirepod/sdkapp/server.go | 50 ++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index 1c932280..4fbea3b7 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -3,6 +3,7 @@ package sdkapp import ( "bytes" "context" + "encoding/binary" "encoding/json" "fmt" "image" @@ -142,11 +143,39 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { } case r.URL.Path == "/api-sdk/display_image": - r.ParseMultipartForm(2 << 20) + r.ParseMultipartForm(3 << 20) imgPath, _, err := r.FormFile("image") + img, _, err := image.Decode(imgPath) + if err != nil { + http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) + return + } + bounds := img.Bounds() + + rgbValues := make([][][3]uint8, bounds.Dy()) // height + + for y := bounds.Min.Y; y < bounds.Max.Y; y++ { + rgbRow := make([][3]uint8, bounds.Dx()) // width + + for x := bounds.Min.X; x < bounds.Max.X; x++ { + //get current pixel color + f := img.At(x, y) + + r, g, b, _ := f.RGBA() + r8 := uint8(r >> 8) + g8 := uint8(g >> 8) + b8 := uint8(b >> 8) + + //store RGB values + rgbRow[x] = [3]uint8{r8, g8, b8} + } + + rgbValues[y] = rgbRow + } + // Lê a imagem e trata possíveis erros - faceBytes, err := io.ReadAll(imgPath) + faceBytes, err := rgbToBytes(rgbValues) if err != nil { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) return @@ -165,6 +194,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { DurationMs: uint32(duration), // Certifique-se de que este campo é exportado InterruptRunning: true, // Certifique-se de que este campo é exportado }) + if err != nil { http.Error(w, "Error displaying face image: "+err.Error(), http.StatusInternalServerError) return @@ -607,3 +637,19 @@ func BeginServer() { } } } + +func rgbToBytes(rgbValues [][][3]uint8) ([]byte, error) { + var buffer bytes.Buffer + + for _, row := range rgbValues { + for _, pixel := range row { + err := binary.Write(&buffer, binary.LittleEndian, pixel) + if err != nil { + return nil, err + } + } + + } + + return buffer.Bytes(), nil +} From a3d31143a51f9b110f530e03352161db64901afa Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 19:18:51 -0300 Subject: [PATCH 03/25] fixing shuffled image --- chipper/pkg/wirepod/sdkapp/server.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index 4fbea3b7..a42426b6 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -3,7 +3,6 @@ package sdkapp import ( "bytes" "context" - "encoding/binary" "encoding/json" "fmt" "image" @@ -643,12 +642,11 @@ func rgbToBytes(rgbValues [][][3]uint8) ([]byte, error) { for _, row := range rgbValues { for _, pixel := range row { - err := binary.Write(&buffer, binary.LittleEndian, pixel) - if err != nil { - return nil, err - } + // Adiciona diretamente os valores R, G e B no buffer + buffer.WriteByte(pixel[2]) // R + buffer.WriteByte(pixel[1]) // G + buffer.WriteByte(pixel[0]) // B } - } return buffer.Bytes(), nil From 34d3b02e1c82c40aab9d8685332eed66c374bec1 Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 19:26:47 -0300 Subject: [PATCH 04/25] Fixing shuffled image (resize img) --- chipper/pkg/wirepod/sdkapp/server.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index a42426b6..a9e317d3 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -20,6 +20,7 @@ import ( "github.com/kercre123/wire-pod/chipper/pkg/logger" "github.com/kercre123/wire-pod/chipper/pkg/scripting" "github.com/kercre123/wire-pod/chipper/pkg/vars" + "github.com/nfnt/resize" ) var serverFiles string = "./webroot/sdkapp" @@ -150,7 +151,8 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) return } - bounds := img.Bounds() + resizedImg := resize.Resize(184, 96, img, resize.Lanczos3) + bounds := resizedImg.Bounds() rgbValues := make([][][3]uint8, bounds.Dy()) // height @@ -643,9 +645,9 @@ func rgbToBytes(rgbValues [][][3]uint8) ([]byte, error) { for _, row := range rgbValues { for _, pixel := range row { // Adiciona diretamente os valores R, G e B no buffer - buffer.WriteByte(pixel[2]) // R + buffer.WriteByte(pixel[0]) // R buffer.WriteByte(pixel[1]) // G - buffer.WriteByte(pixel[0]) // B + buffer.WriteByte(pixel[2]) // B } } From e181f472c26ce137b4d9f2bb6fa517b13f247e5f Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 19:53:18 -0300 Subject: [PATCH 05/25] Fixing shuffled image (resize img) --- chipper/pkg/wirepod/sdkapp/server.go | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index a9e317d3..cbbd70a5 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -20,7 +20,6 @@ import ( "github.com/kercre123/wire-pod/chipper/pkg/logger" "github.com/kercre123/wire-pod/chipper/pkg/scripting" "github.com/kercre123/wire-pod/chipper/pkg/vars" - "github.com/nfnt/resize" ) var serverFiles string = "./webroot/sdkapp" @@ -151,7 +150,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) return } - resizedImg := resize.Resize(184, 96, img, resize.Lanczos3) + resizedImg := resizeImage(img, 184, 96) bounds := resizedImg.Bounds() rgbValues := make([][][3]uint8, bounds.Dy()) // height @@ -653,3 +652,24 @@ func rgbToBytes(rgbValues [][][3]uint8) ([]byte, error) { return buffer.Bytes(), nil } + +func resizeImage(original image.Image, width, height int) image.Image { + if width <= 0 || height <= 0 { + return original + } + + newImage := image.NewRGBA(image.Rect(0, 0, width, height)) + + scaleX := float64(original.Bounds().Dx()) / float64(width) + scaleY := float64(original.Bounds().Dy()) / float64(height) + + for y := 0; y < height; y++ { + for x := 0; x < width; x++ { + srcX := int(float64(x) * scaleX) + srcY := int(float64(y) * scaleY) + newImage.Set(x, y, original.At(srcX, srcY)) + } + } + + return newImage +} From d91508a973298d2b24da1056a2c2b1a6ab16bcfd Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 20:33:58 -0300 Subject: [PATCH 06/25] Fixing shuffled image (BGR) --- chipper/pkg/wirepod/sdkapp/server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index cbbd70a5..64f92a41 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -644,9 +644,9 @@ func rgbToBytes(rgbValues [][][3]uint8) ([]byte, error) { for _, row := range rgbValues { for _, pixel := range row { // Adiciona diretamente os valores R, G e B no buffer - buffer.WriteByte(pixel[0]) // R + buffer.WriteByte(pixel[2]) // R buffer.WriteByte(pixel[1]) // G - buffer.WriteByte(pixel[2]) // B + buffer.WriteByte(pixel[0]) // B } } From a3b5f22c3adab4cdcab4ab17b9361021bb003b47 Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 20:45:13 -0300 Subject: [PATCH 07/25] Fixing shuffled image (rgb) --- chipper/pkg/wirepod/sdkapp/server.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index 64f92a41..e3c43446 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -151,6 +151,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { return } resizedImg := resizeImage(img, 184, 96) + bounds := resizedImg.Bounds() rgbValues := make([][][3]uint8, bounds.Dy()) // height @@ -160,7 +161,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { for x := bounds.Min.X; x < bounds.Max.X; x++ { //get current pixel color - f := img.At(x, y) + f := resizedImg.At(x, y) r, g, b, _ := f.RGBA() r8 := uint8(r >> 8) From dc37e15a6faf67796ac824549953067cea919edf Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 21:18:17 -0300 Subject: [PATCH 08/25] Fixing shuffled image (rgb) --- chipper/pkg/wirepod/sdkapp/server.go | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index e3c43446..7699f2aa 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -175,7 +175,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { rgbValues[y] = rgbRow } - // Lê a imagem e trata possíveis erros + // Reads the image and handles possible errors faceBytes, err := rgbToBytes(rgbValues) if err != nil { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) @@ -186,14 +186,13 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithTimeout(ctx, 15*time.Second) defer cancel() - // Defina a duração e o bloqueio - duration := 3000 // Duração em milissegundos + duration := 3000 - // Chamada da função DisplayFaceImageRGB e tratamento de erro + // call DisplayFaceImageRGB e handle error resp, err := robot.Conn.DisplayFaceImageRGB(ctx, &vectorpb.DisplayFaceImageRGBRequest{ - FaceData: faceBytes, // Certifique-se de que este campo é exportado - DurationMs: uint32(duration), // Certifique-se de que este campo é exportado - InterruptRunning: true, // Certifique-se de que este campo é exportado + FaceData: faceBytes, + DurationMs: uint32(duration), + InterruptRunning: true, }) if err != nil { @@ -201,7 +200,6 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { return } - // Responda com um status de sucesso fmt.Fprintf(w, "Face image displayed successfully: %+v", resp) return @@ -644,10 +642,10 @@ func rgbToBytes(rgbValues [][][3]uint8) ([]byte, error) { for _, row := range rgbValues { for _, pixel := range row { - // Adiciona diretamente os valores R, G e B no buffer - buffer.WriteByte(pixel[2]) // R + // Directly add the R, G and B values ​​to the buffer + buffer.WriteByte(pixel[0]) // R buffer.WriteByte(pixel[1]) // G - buffer.WriteByte(pixel[0]) // B + buffer.WriteByte(pixel[2]) // B } } From a8c32cf1c0623e2b1407968e6a6762e26e241b6c Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 21:29:47 -0300 Subject: [PATCH 09/25] Fixing shuffled image (without resize) --- chipper/pkg/wirepod/sdkapp/server.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index 7699f2aa..20fa4b3a 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -150,9 +150,9 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) return } - resizedImg := resizeImage(img, 184, 96) + //resizedImg := resizeImage(img, 184, 96) - bounds := resizedImg.Bounds() + bounds := img.Bounds() rgbValues := make([][][3]uint8, bounds.Dy()) // height @@ -161,7 +161,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { for x := bounds.Min.X; x < bounds.Max.X; x++ { //get current pixel color - f := resizedImg.At(x, y) + f := img.At(x, y) r, g, b, _ := f.RGBA() r8 := uint8(r >> 8) From cbb3ef0ec5aed2d4e9595c8b4c20e0cb75176b81 Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 21:43:26 -0300 Subject: [PATCH 10/25] Fixing shuffled image (without resize) --- chipper/pkg/wirepod/sdkapp/server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index 20fa4b3a..8119c8e0 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -176,7 +176,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { } // Reads the image and handles possible errors - faceBytes, err := rgbToBytes(rgbValues) + //faceBytes, err := rgbToBytes(rgbValues) if err != nil { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) return @@ -190,7 +190,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { // call DisplayFaceImageRGB e handle error resp, err := robot.Conn.DisplayFaceImageRGB(ctx, &vectorpb.DisplayFaceImageRGBRequest{ - FaceData: faceBytes, + FaceData: rgbValues, DurationMs: uint32(duration), InterruptRunning: true, }) From b01576cf36024ffa347e0076e1f6cbd0fff9382b Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 21:56:23 -0300 Subject: [PATCH 11/25] Fixing shuffled image (solid color) --- chipper/pkg/wirepod/sdkapp/server.go | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index 8119c8e0..b1dc1aca 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -6,7 +6,9 @@ import ( "encoding/json" "fmt" "image" + "image/color" "image/jpeg" + "image/png" "io" "net/http" "os" @@ -142,10 +144,20 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { } case r.URL.Path == "/api-sdk/display_image": - r.ParseMultipartForm(3 << 20) - imgPath, _, err := r.FormFile("image") + //r.ParseMultipartForm(3 << 20) + //imgPath, _, err := r.FormFile("image") - img, _, err := image.Decode(imgPath) + //defer imgPath.Close() + imgT := image.NewRGBA(image.Rect(0, 0, 184, 96)) + for y := 0; y < 96; y++ { + for x := 0; x < 184; x++ { + imgT.Set(x, y, color.RGBA{0, 255, 0, 255}) // Verde + } + } + f, _ := os.Create("solid_green.png") + defer f.Close() + png.Encode(f, imgT) + img := imgT if err != nil { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) return @@ -176,7 +188,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { } // Reads the image and handles possible errors - //faceBytes, err := rgbToBytes(rgbValues) + faceBytes, err := rgbToBytes(rgbValues) if err != nil { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) return @@ -190,7 +202,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { // call DisplayFaceImageRGB e handle error resp, err := robot.Conn.DisplayFaceImageRGB(ctx, &vectorpb.DisplayFaceImageRGBRequest{ - FaceData: rgbValues, + FaceData: faceBytes, DurationMs: uint32(duration), InterruptRunning: true, }) From b35a129d0d1a807361c35e3ea959cb12ad431f46 Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 22:01:36 -0300 Subject: [PATCH 12/25] Fixing shuffled image (solid color) --- chipper/pkg/wirepod/sdkapp/server.go | 29 +++++++++++++--------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index b1dc1aca..fd3ebaca 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -6,9 +6,7 @@ import ( "encoding/json" "fmt" "image" - "image/color" "image/jpeg" - "image/png" "io" "net/http" "os" @@ -144,20 +142,19 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { } case r.URL.Path == "/api-sdk/display_image": - //r.ParseMultipartForm(3 << 20) - //imgPath, _, err := r.FormFile("image") + r.ParseMultipartForm(3 << 20) + imgPath, _, err := r.FormFile("image") - //defer imgPath.Close() - imgT := image.NewRGBA(image.Rect(0, 0, 184, 96)) - for y := 0; y < 96; y++ { - for x := 0; x < 184; x++ { - imgT.Set(x, y, color.RGBA{0, 255, 0, 255}) // Verde - } + defer imgPath.Close() + + solidFaceBytes := make([]byte, 17664*3) // 17664 pixels, 3 bytes por pixel + for i := 0; i < len(solidFaceBytes); i += 3 { + solidFaceBytes[i] = 0 // R + solidFaceBytes[i+1] = 255 // G + solidFaceBytes[i+2] = 0 // B } - f, _ := os.Create("solid_green.png") - defer f.Close() - png.Encode(f, imgT) - img := imgT + + img, _, err := image.Decode(imgPath) if err != nil { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) return @@ -188,7 +185,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { } // Reads the image and handles possible errors - faceBytes, err := rgbToBytes(rgbValues) + //faceBytes, err := rgbToBytes(rgbValues) if err != nil { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) return @@ -202,7 +199,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { // call DisplayFaceImageRGB e handle error resp, err := robot.Conn.DisplayFaceImageRGB(ctx, &vectorpb.DisplayFaceImageRGBRequest{ - FaceData: faceBytes, + FaceData: solidFaceBytes, DurationMs: uint32(duration), InterruptRunning: true, }) From 32f75a25f8192fe793af9c4968ad73d275b32e9f Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 22:06:48 -0300 Subject: [PATCH 13/25] Fixing shuffled image (solid color) --- chipper/pkg/wirepod/sdkapp/server.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index fd3ebaca..74599b4a 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -149,9 +149,9 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { solidFaceBytes := make([]byte, 17664*3) // 17664 pixels, 3 bytes por pixel for i := 0; i < len(solidFaceBytes); i += 3 { - solidFaceBytes[i] = 0 // R - solidFaceBytes[i+1] = 255 // G - solidFaceBytes[i+2] = 0 // B + solidFaceBytes[i] = 255 // R + solidFaceBytes[i+1] = 0 // G + solidFaceBytes[i+2] = 0 // B } img, _, err := image.Decode(imgPath) From 8f979aa420ac332d6c7fad627067cd6097251dae Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 22:09:37 -0300 Subject: [PATCH 14/25] Fixing shuffled image (solid color) --- chipper/pkg/wirepod/sdkapp/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index 74599b4a..38d16645 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -147,7 +147,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { defer imgPath.Close() - solidFaceBytes := make([]byte, 17664*3) // 17664 pixels, 3 bytes por pixel + solidFaceBytes := make([]byte, 17664*1) // 17664 pixels, 3 bytes por pixel for i := 0; i < len(solidFaceBytes); i += 3 { solidFaceBytes[i] = 255 // R solidFaceBytes[i+1] = 0 // G From b089690f60dabd2c2dbb96b6dff5e4e1e0515990 Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 22:11:14 -0300 Subject: [PATCH 15/25] Fixing shuffled image (solid color) --- chipper/pkg/wirepod/sdkapp/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index 38d16645..2f05dfdd 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -147,7 +147,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { defer imgPath.Close() - solidFaceBytes := make([]byte, 17664*1) // 17664 pixels, 3 bytes por pixel + solidFaceBytes := make([]byte, 17664*10) // 17664 pixels, 3 bytes por pixel for i := 0; i < len(solidFaceBytes); i += 3 { solidFaceBytes[i] = 255 // R solidFaceBytes[i+1] = 0 // G From e32a369e76a08012d0f54db41f245146e480fad9 Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 22:28:16 -0300 Subject: [PATCH 16/25] Fixing shuffled image --- chipper/pkg/wirepod/sdkapp/server.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index 2f05dfdd..827014a1 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -147,13 +147,6 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { defer imgPath.Close() - solidFaceBytes := make([]byte, 17664*10) // 17664 pixels, 3 bytes por pixel - for i := 0; i < len(solidFaceBytes); i += 3 { - solidFaceBytes[i] = 255 // R - solidFaceBytes[i+1] = 0 // G - solidFaceBytes[i+2] = 0 // B - } - img, _, err := image.Decode(imgPath) if err != nil { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) @@ -185,7 +178,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { } // Reads the image and handles possible errors - //faceBytes, err := rgbToBytes(rgbValues) + faceBytes, err := rgbToBytes(rgbValues) if err != nil { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) return @@ -199,7 +192,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { // call DisplayFaceImageRGB e handle error resp, err := robot.Conn.DisplayFaceImageRGB(ctx, &vectorpb.DisplayFaceImageRGBRequest{ - FaceData: solidFaceBytes, + FaceData: faceBytes, DurationMs: uint32(duration), InterruptRunning: true, }) From e0c01b1c7fb401d8982a54e635485de698a5e552 Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sat, 21 Sep 2024 22:54:43 -0300 Subject: [PATCH 17/25] Fixing shuffled image --- chipper/pkg/wirepod/sdkapp/server.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index 827014a1..a5cd9541 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -178,7 +178,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { } // Reads the image and handles possible errors - faceBytes, err := rgbToBytes(rgbValues) + faceBytes, err := imageToBytes(img) if err != nil { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) return @@ -653,6 +653,25 @@ func rgbToBytes(rgbValues [][][3]uint8) ([]byte, error) { return buffer.Bytes(), nil } +func imageToBytes(img image.Image) ([]byte, error) { + bounds := img.Bounds() + var buffer bytes.Buffer + + for y := bounds.Min.Y; y < bounds.Max.Y; y++ { + for x := bounds.Min.X; x < bounds.Max.X; x++ { + // Obtém a cor do pixel + c := img.At(x, y) + r, g, b, _ := c.RGBA() // Ignorando o valor Alpha + + // Converte de uint32 para uint8 + buffer.WriteByte(uint8(r >> 8)) + buffer.WriteByte(uint8(g >> 8)) + buffer.WriteByte(uint8(b >> 8)) + } + } + + return buffer.Bytes(), nil +} func resizeImage(original image.Image, width, height int) image.Image { if width <= 0 || height <= 0 { From 4394fe047914dd29a35fcb094c27bf9def9b83cd Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sun, 22 Sep 2024 18:06:18 -0300 Subject: [PATCH 18/25] Fixing shuffled image --- chipper/pkg/wirepod/sdkapp/server.go | 37 +++++++++++++++------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index a5cd9541..963b68d0 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -7,6 +7,7 @@ import ( "fmt" "image" "image/jpeg" + "image/png" "io" "net/http" "os" @@ -154,36 +155,38 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { } //resizedImg := resizeImage(img, 184, 96) - bounds := img.Bounds() + // bounds := img.Bounds() - rgbValues := make([][][3]uint8, bounds.Dy()) // height + // rgbValues := make([][][3]uint8, bounds.Dy()) // height - for y := bounds.Min.Y; y < bounds.Max.Y; y++ { - rgbRow := make([][3]uint8, bounds.Dx()) // width + // for y := bounds.Min.Y; y < bounds.Max.Y; y++ { + // rgbRow := make([][3]uint8, bounds.Dx()) // width - for x := bounds.Min.X; x < bounds.Max.X; x++ { - //get current pixel color - f := img.At(x, y) + // for x := bounds.Min.X; x < bounds.Max.X; x++ { + // //get current pixel color + // f := img.At(x, y) - r, g, b, _ := f.RGBA() - r8 := uint8(r >> 8) - g8 := uint8(g >> 8) - b8 := uint8(b >> 8) + // r, g, b, _ := f.RGBA() + // r8 := uint8(r >> 8) + // g8 := uint8(g >> 8) + // b8 := uint8(b >> 8) - //store RGB values - rgbRow[x] = [3]uint8{r8, g8, b8} - } + // //store RGB values + // rgbRow[x] = [3]uint8{r8, g8, b8} + // } - rgbValues[y] = rgbRow - } + // rgbValues[y] = rgbRow + // } // Reads the image and handles possible errors - faceBytes, err := imageToBytes(img) + var buf bytes.Buffer + err = png.Encode(&buf, img) if err != nil { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) return } + faceBytes := buf.Bytes() ctx := r.Context() ctx, cancel := context.WithTimeout(ctx, 15*time.Second) defer cancel() From b077b21123f57f662d26fb23e639a19c0cd51d6a Mon Sep 17 00:00:00 2001 From: F4310sp Date: Sun, 22 Sep 2024 18:10:37 -0300 Subject: [PATCH 19/25] Fixing shuffled image --- chipper/pkg/wirepod/sdkapp/server.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index 963b68d0..d952570b 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -7,7 +7,6 @@ import ( "fmt" "image" "image/jpeg" - "image/png" "io" "net/http" "os" @@ -179,14 +178,12 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { // } // Reads the image and handles possible errors - var buf bytes.Buffer - err = png.Encode(&buf, img) + faceBytes, err := imageToBytes(img) if err != nil { http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) return } - faceBytes := buf.Bytes() ctx := r.Context() ctx, cancel := context.WithTimeout(ctx, 15*time.Second) defer cancel() From fa805bfaacea3846056e40c2f105d4ee57b13799 Mon Sep 17 00:00:00 2001 From: F4310sp Date: Mon, 23 Sep 2024 12:37:50 -0300 Subject: [PATCH 20/25] Play_sound --- chipper/pkg/wirepod/sdkapp/server.go | 86 ++++++++++++---------------- 1 file changed, 37 insertions(+), 49 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index d952570b..b87c8a9a 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -140,69 +140,57 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte(json)) return } - case r.URL.Path == "/api-sdk/display_image": - r.ParseMultipartForm(3 << 20) - imgPath, _, err := r.FormFile("image") - - defer imgPath.Close() - - img, _, err := image.Decode(imgPath) + case r.URL.Path == "/api-sdk/play_sound": + file, _, err := r.FormFile("sound") if err != nil { - http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) + println("Error retrieving the file:", err) return } - //resizedImg := resizeImage(img, 184, 96) - - // bounds := img.Bounds() - - // rgbValues := make([][][3]uint8, bounds.Dy()) // height - - // for y := bounds.Min.Y; y < bounds.Max.Y; y++ { - // rgbRow := make([][3]uint8, bounds.Dx()) // width - - // for x := bounds.Min.X; x < bounds.Max.X; x++ { - // //get current pixel color - // f := img.At(x, y) + defer file.Close() - // r, g, b, _ := f.RGBA() - // r8 := uint8(r >> 8) - // g8 := uint8(g >> 8) - // b8 := uint8(b >> 8) - - // //store RGB values - // rgbRow[x] = [3]uint8{r8, g8, b8} - // } - - // rgbValues[y] = rgbRow - // } - - // Reads the image and handles possible errors - faceBytes, err := imageToBytes(img) + // Lê o conteúdo do arquivo em um slice de bytes + pcmFile, err := io.ReadAll(file) if err != nil { - http.Error(w, "Error reading image: "+err.Error(), http.StatusInternalServerError) + println("Error reading the file:", err) return } - ctx := r.Context() - ctx, cancel := context.WithTimeout(ctx, 15*time.Second) - defer cancel() - - duration := 3000 + var audioChunks [][]byte + for len(pcmFile) >= 1024 { + audioChunks = append(audioChunks, pcmFile[:1024]) + pcmFile = pcmFile[1024:] + } - // call DisplayFaceImageRGB e handle error - resp, err := robot.Conn.DisplayFaceImageRGB(ctx, &vectorpb.DisplayFaceImageRGBRequest{ - FaceData: faceBytes, - DurationMs: uint32(duration), - InterruptRunning: true, + var audioClient vectorpb.ExternalInterface_ExternalAudioStreamPlaybackClient + audioClient, _ = robot.Conn.ExternalAudioStreamPlayback(ctx) + audioClient.SendMsg(&vectorpb.ExternalAudioStreamRequest{ + AudioRequestType: &vectorpb.ExternalAudioStreamRequest_AudioStreamPrepare{ + AudioStreamPrepare: &vectorpb.ExternalAudioStreamPrepare{ + AudioFrameRate: 16000, + AudioVolume: uint32(100), + }, + }, }) - if err != nil { - http.Error(w, "Error displaying face image: "+err.Error(), http.StatusInternalServerError) - return + for _, chunk := range audioChunks { + audioClient.SendMsg(&vectorpb.ExternalAudioStreamRequest{ + AudioRequestType: &vectorpb.ExternalAudioStreamRequest_AudioStreamChunk{ + AudioStreamChunk: &vectorpb.ExternalAudioStreamChunk{ + AudioChunkSizeBytes: uint32(len(chunk)), + AudioChunkSamples: chunk, + }, + }, + }) + time.Sleep(time.Millisecond * 30) } - fmt.Fprintf(w, "Face image displayed successfully: %+v", resp) + audioClient.SendMsg(&vectorpb.ExternalAudioStreamRequest{ + AudioRequestType: &vectorpb.ExternalAudioStreamRequest_AudioStreamComplete{ + AudioStreamComplete: &vectorpb.ExternalAudioStreamComplete{}, + }, + }) + return case r.URL.Path == "/api-sdk/get_battery": From 8ee1746bda4744b53d8b281b0b26baec7f04d264 Mon Sep 17 00:00:00 2001 From: F4310sp Date: Mon, 23 Sep 2024 21:09:31 -0300 Subject: [PATCH 21/25] Play Audio Wav FrameRate 8000Hz --- chipper/pkg/wirepod/sdkapp/server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chipper/pkg/wirepod/sdkapp/server.go b/chipper/pkg/wirepod/sdkapp/server.go index b87c8a9a..9543c067 100755 --- a/chipper/pkg/wirepod/sdkapp/server.go +++ b/chipper/pkg/wirepod/sdkapp/server.go @@ -167,7 +167,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { audioClient.SendMsg(&vectorpb.ExternalAudioStreamRequest{ AudioRequestType: &vectorpb.ExternalAudioStreamRequest_AudioStreamPrepare{ AudioStreamPrepare: &vectorpb.ExternalAudioStreamPrepare{ - AudioFrameRate: 16000, + AudioFrameRate: 8000, AudioVolume: uint32(100), }, }, @@ -182,7 +182,7 @@ func SdkapiHandler(w http.ResponseWriter, r *http.Request) { }, }, }) - time.Sleep(time.Millisecond * 30) + time.Sleep(time.Millisecond * 60) } audioClient.SendMsg(&vectorpb.ExternalAudioStreamRequest{ From 043c8de43ad490df958cb359723847c1eabae8e3 Mon Sep 17 00:00:00 2001 From: Fabio Date: Tue, 24 Sep 2024 15:56:11 -0300 Subject: [PATCH 22/25] Added FrameRate convert (play_audio.js) and html upload audio (control.html) --- chipper/webroot/js/play_audio.js | 125 ++++++++++++++++++++++++++++ chipper/webroot/sdkapp/control.html | 13 +++ 2 files changed, 138 insertions(+) create mode 100644 chipper/webroot/js/play_audio.js diff --git a/chipper/webroot/js/play_audio.js b/chipper/webroot/js/play_audio.js new file mode 100644 index 00000000..9c41f3fd --- /dev/null +++ b/chipper/webroot/js/play_audio.js @@ -0,0 +1,125 @@ + +//Convert the WAV frame rate on the client machine and send the WAV file to be processed at /api-sdk/play_sound + +let processedAudioBlob = null; + +document.getElementById('fileInput').addEventListener('change', async () => { + const fileInput = document.getElementById('fileInput'); + if (!fileInput.files.length) { + alert('Please, select a WAV file'); + return; + } + + const file = fileInput.files[0]; + const arrayBuffer = await file.arrayBuffer(); + const audioContext = new (window.AudioContext || window.webkitAudioContext)(); + + try { + const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); + + // adjust frame rate to 8000 Hz + const newSampleRate = 8000; + const newLength = Math.round(audioBuffer.length * newSampleRate / audioBuffer.sampleRate); + const newBuffer = audioContext.createBuffer(audioBuffer.numberOfChannels, newLength, newSampleRate); + + for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) { + const oldData = audioBuffer.getChannelData(channel); + const newData = newBuffer.getChannelData(channel); + + for (let i = 0; i < newLength; i++) { + const oldIndex = i * audioBuffer.sampleRate / newSampleRate; + const index0 = Math.floor(oldIndex); + const index1 = Math.min(index0 + 1, oldData.length - 1); + const fraction = oldIndex - index0; + + newData[i] = oldData[index0] * (1 - fraction) + oldData[index1] * fraction; + } + } + + // Create a new WAV file + processedAudioBlob = await bufferToWave(newBuffer); + const url = URL.createObjectURL(processedAudioBlob); + + // play processed audio + const audioOutput = document.getElementById('audioOutput'); + audioOutput.src = url; + audioOutput.play(); + + // show send button + document.getElementById('uploadButton').style.display = 'inline-block'; + } catch (error) { + console.error('Error processing the file:', error); + } +}); + +function bufferToWave(abuffer) { + const numOfChannels = abuffer.numberOfChannels; + const length = abuffer.length * numOfChannels * 2 + 44; + const buffer = new ArrayBuffer(length); + const view = new DataView(buffer); + let offset = 0; + + // Escrever cabeçalho WAV + setString(view, offset, 'RIFF'); offset += 4; + view.setUint32(offset, length - 8, true); offset += 4; + setString(view, offset, 'WAVE'); offset += 4; + setString(view, offset, 'fmt '); offset += 4; + view.setUint32(offset, 16, true); offset += 4; // format size + view.setUint16(offset, 1, true); offset += 2; // PCM format + view.setUint16(offset, numOfChannels, true); offset += 2; // number of channels + view.setUint32(offset, 8000, true); offset += 4; // sample rate + view.setUint32(offset, 8000 * numOfChannels * 2, true); offset += 4; // byte rate + view.setUint16(offset, numOfChannels * 2, true); offset += 2; // block align + view.setUint16(offset, 16, true); offset += 2; // bits per sample + + setString(view, offset, 'data'); offset += 4; + view.setUint32(offset, length - offset - 4, true); offset += 4; + + // Copiar os dados de áudio + for (let channel = 0; channel < numOfChannels; channel++) { + const channelData = abuffer.getChannelData(channel); + for (let i = 0; i < channelData.length; i++) { + view.setInt16(offset, channelData[i] * 0x7FFF, true); + offset += 2; + } + } + + return new Blob([buffer], { type: 'audio/wav' }); +} + +function setString(view, offset, string) { + for (let i = 0; i < string.length; i++) { + view.setUint8(offset + i, string.charCodeAt(i)); + } +} + +document.getElementById('uploadButton').addEventListener('click', async () => { + if (!processedAudioBlob) { + alert('No processed audio to send.'); + return; + } + + await uploadAudio(processedAudioBlob); +}); + +async function uploadAudio(blob) { + const formData = new FormData(); + formData.append('sound', blob, 'processed.wav'); + + try { + const dominio = window.location.hostname; + const response = await fetch(dominio + '/api-sdk/play_sound', { + method: 'POST', + body: formData, + }); + + if (!response.ok) { + throw new Error('Erro to send audio: ' + response.statusText); + } + + const result = await response.json(); + console.log('Audio sent successfully:', result); + } catch (error) { + console.error('Error sending audio:', error); + } +} diff --git a/chipper/webroot/sdkapp/control.html b/chipper/webroot/sdkapp/control.html index df6ba71a..5ee5d372 100755 --- a/chipper/webroot/sdkapp/control.html +++ b/chipper/webroot/sdkapp/control.html @@ -88,6 +88,17 @@

Say Text


+

Play Audio

+
+ +
+ +
+ +
+ + +

@@ -98,6 +109,8 @@

Say Text

+ + From a73658a8a88921e774afef66ac3e1711ba1ffbcb Mon Sep 17 00:00:00 2001 From: F4310sp Date: Tue, 24 Sep 2024 16:19:04 -0300 Subject: [PATCH 23/25] Added FrameRate convert (play_audio.js) and html upload audio (control.html) --- chipper/webroot/sdkapp/control.html | 1 - 1 file changed, 1 deletion(-) diff --git a/chipper/webroot/sdkapp/control.html b/chipper/webroot/sdkapp/control.html index 5ee5d372..d6dd4609 100755 --- a/chipper/webroot/sdkapp/control.html +++ b/chipper/webroot/sdkapp/control.html @@ -96,7 +96,6 @@

Play Audio

-
From 88bf62d047def784d8b8b33d8c284a82922108ef Mon Sep 17 00:00:00 2001 From: F4310sp Date: Tue, 24 Sep 2024 21:10:55 -0300 Subject: [PATCH 24/25] Align Adjustment --- chipper/webroot/sdkapp/control.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chipper/webroot/sdkapp/control.html b/chipper/webroot/sdkapp/control.html index d6dd4609..5ff46239 100755 --- a/chipper/webroot/sdkapp/control.html +++ b/chipper/webroot/sdkapp/control.html @@ -86,7 +86,6 @@

Say Text

-

Play Audio

@@ -99,6 +98,7 @@

Play Audio


+
From 997fcb3f61463c057337691fc5fe2baeeed3c6ed Mon Sep 17 00:00:00 2001 From: F4310sp Date: Tue, 24 Sep 2024 21:32:09 -0300 Subject: [PATCH 25/25] ESN detect Adjustment --- chipper/webroot/js/play_audio.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chipper/webroot/js/play_audio.js b/chipper/webroot/js/play_audio.js index 9c41f3fd..868f0544 100644 --- a/chipper/webroot/js/play_audio.js +++ b/chipper/webroot/js/play_audio.js @@ -108,7 +108,8 @@ async function uploadAudio(blob) { try { const dominio = window.location.hostname; - const response = await fetch(dominio + '/api-sdk/play_sound', { + esn = urlParams.get("serial"); + const response = await fetch('/api-sdk/play_sound?serial='+esn, { method: 'POST', body: formData, });