{"id":26154450,"url":"https://github.com/binozo/echogo","last_synced_at":"2026-05-20T16:39:15.031Z","repository":{"id":212935888,"uuid":"714067660","full_name":"Binozo/EchoGo","owner":"Binozo","description":"A Go SDK for developing Software for your Echo Dot","archived":false,"fork":false,"pushed_at":"2025-04-20T17:02:19.000Z","size":49090,"stargazers_count":4,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-01T01:02:19.384Z","etag":null,"topics":["alexa","go","tinyalsa"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Binozo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-11-03T21:03:59.000Z","updated_at":"2025-06-13T10:35:39.000Z","dependencies_parsed_at":"2023-12-31T00:32:14.109Z","dependency_job_id":"0ea50e42-ad19-4087-aadb-0845c5f47bdb","html_url":"https://github.com/Binozo/EchoGo","commit_stats":null,"previous_names":["binozo/echogosdk"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/Binozo/EchoGo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Binozo%2FEchoGo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Binozo%2FEchoGo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Binozo%2FEchoGo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Binozo%2FEchoGo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Binozo","download_url":"https://codeload.github.com/Binozo/EchoGo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Binozo%2FEchoGo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33267094,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-20T15:12:43.734Z","status":"ssl_error","status_checked_at":"2026-05-20T15:12:42.300Z","response_time":356,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alexa","go","tinyalsa"],"created_at":"2025-03-11T08:29:36.015Z","updated_at":"2026-05-20T16:39:15.024Z","avatar_url":"https://github.com/Binozo.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\u003ch3 align=\"center\"\u003eEchoGo\u003c/h3\u003e\n\n  \u003cp align=\"center\"\u003e\n    A Go SDK for your Echo Dot \u003cb\u003e2. Gen\u003c/b\u003e\n    \u003cbr /\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n\u003cimg src=\"assets/thumbnail.gif\"\u003e\n\n## ⚡ Features\n- 🚥 Full control over LEDs\n- 🎤 Access to microphone, speaker and buttons\n- ⚙️ Preconfigured compiler\n\n## 🗣️ Quick pre yapping \n\nAs I am building my privacy focused smart home I wanted an assistant like Alexa or Google Home to talk to. I already owned an Alexa Echo Dot 2. Gen so I decided to take full control of it.\nThanks to [Dragon863's Project](https://github.com/Dragon863/EchoCLI) I was able to do this and create an SDK for it.\nWith this SDK you take full control over your Echo and you can abuse it as you wish. You get full root access.\n\n\u003cdetails\u003e\n  \u003csummary\u003eSome interesting facts\u003c/summary\u003e\n  \u003col\u003e\n    \u003cli\u003e🤫 The mute button seems to be a hardware button. If you access the microphone while the microphone is muted you will get an empty byte stream.\u003c/li\u003e\n    \u003cli\u003e🎨 The LEDs fully support RGB, you are not limited to Blue and Red colors.\u003c/li\u003e\n    \u003cli\u003e🛜 You can find saved Wi-Fi connections at \u003ccode\u003e/data/misc/wifi/wpa_supplicant.conf\u003c/code\u003e\u003c/li\u003e\n    \u003cli\u003e🔊 Uses TinyAlsa under the hood; Microphone has 9 channels while the speaker has 2 channels\u003c/li\u003e\n    \u003cli\u003e🤖 The echo is actually an Android 7 device\u003c/li\u003e\n  \u003c/ol\u003e\n  \u003cp\u003e\u003c/p\u003e\n\u003c/details\u003e\n\n\n## 📋 Requirements\n- A fully rooted Echo Dot **2. Gen** ([Dragon863's Project](https://github.com/Dragon863/EchoCLI))\n- You need your `preloader_no_hdr.bin` file for booting\n- A linux machine (This project has not been tested on Windows and Mac)\n- If you wish to compile the server yourself you need Docker installed\n\n\u003e [!CAUTION]\n\u003e Make sure your echo is not able to connect to the Internet. Use a temporary hotspot for setup if needed, make sure the Echo can't reach the Wi-Fi network after that otherwise your echo may get bricked after a few days/weeks due to OTA updates.\n\n## 👷‍♂️ Setup\nFirst make sure you rooted your Echo. Take a look at this guide [here](https://danieldb.uk/posts/alexa-2/).\n\nThis project consists of two parts: The host controller and the echo server.\n\nThe echo server runs on the echo and allows clients to control the echo through HTTP.\nThe host controller takes care of booting the echo and setting it up. Additionally, it can control it too.\n\nNow let's get to the `SHIP IT 🚀`-part.\n\n### Server\n\nTo control the echo remotely you need to run a server on it.\nEither you can download it prebuilt from GitHub or you compile it yourself.\n\nFor both refer to the [CLI](#-cli) section.\n\n### Host\nOpen your terminal in your project and first import this package:\n```shell\n$ go get -u https://github.com/Binozo/EchoGo/v3\n```\n\nAlso make sure you got your `preloader_no_hdr.bin` file in your project root or working directory.\n\nThen install mtkclient:\n```shell\n$ git clone --depth=1 --branch 2.0.1 https://github.com/bkerler/mtkclient.git\n$ git submodule update --recursive\n# Install python dependencies\n$ cd mtkclient\n$ python -m venv .venv\n$ source .venv/bin/activate\n$ pip install -r requirements.txt\n$ pip install .\n```\n\nNow we actually ship 🚀\n\nHere is a full Go example. This shows the use of every component of the echo including LEDs, buttons, microphones and the speaker.\n\nPress the dot button once to start recording. Then press the dot button again to stop recording and the echo will play your recording through the speakers.\nThis code must be run on the host machine. I recommend you to use this code as a starting point in your project as it already handles the booting process. Modify it as you wish.\n\n\u003e [!NOTE]  \n\u003e This code may crash on the first time because the echo server needs to be deployed first. The server must be started by the android system itself which only happens on boot. Refer to the [CLI](#-cli) section to deploy the server first, reboot and then run this code.\n\n```go\npackage main\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"github.com/Binozo/EchoGo/v3/pkg/buttons\"\n\t\"github.com/Binozo/EchoGo/v3/pkg/echo\"\n\t\"github.com/Binozo/EchoGo/v3/pkg/led\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"time\"\n)\n\nfunc main() {\n\tlog.SetOutput(os.Stdout)\n\tlog.Println(\"Starting up...\")\n\n\talexa, err := echo.New()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tisOnline, err := alexa.IsOnline()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tif !isOnline {\n\t\tlog.Println(\"Alexa is not online. Booting...\")\n\t\tif err = alexa.Boot(echo.DefaultPreloaderPath); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\t// !!! We need to sleep here for 5 seconds because executing `alexa.Deploy()` disables SELinux enforcing\n\t\t// Doing this too early in the boot process breaks the microphone access functionality\n\t\ttime.Sleep(5 * time.Second)\n\t\tlog.Println(\"Deploying server app to alexa...\")\n\t\tif err = alexa.Deploy(echo.DefaultServerPath); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tlog.Println(\"Bootup completed\")\n\t\ttime.Sleep(time.Second)\n\t} else {\n\t\tlog.Println(\"Alexa is already online\")\n\n\t\t// Check if server is online\n\t\tif err = alexa.Ping(); err != nil {\n\t\t\tlog.Println(\"Server is not reachable. Starting...\")\n\t\t\tif err = alexa.Deploy(echo.DefaultServerPath); err != nil {\n\t\t\t\tlog.Fatal(err)\n\t\t\t}\n\t\t\ttime.Sleep(time.Second)\n\t\t}\n\t}\n\n\t// Custom code\n\n\tbtn := alexa.GetButtonController()\n\tledController := alexa.GetLedController()\n\tmic := alexa.GetMicrophone()\n\tspeaker := alexa.GetSpeaker()\n\n\tlog.Println(\"Press the Dot button to start recording\")\n\tclearLeds(ledController)\n\tledController.SetLEDs(led.Led{\n\t\tID: 7,\n\t\tR:  255,\n\t\tG:  255,\n\t\tB:  255,\n\t}, led.Led{\n\t\tID: 8,\n\t\tR:  255,\n\t\tG:  255,\n\t\tB:  255,\n\t})\n\n\trecording := false\n\tanimatingCtx, cancel := context.WithCancel(context.Background())\n\tvar recordingBuffer bytes.Buffer\n\tbtnSub, err := btn.SubscribeToButton(func(event buttons.ButtonClickEvent) {\n\t\tif event.ClickType == buttons.DotClick \u0026\u0026 !event.Down {\n\t\t\tif recording {\n\t\t\t\tcancel()\n\t\t\t\tclearLeds(ledController)\n\t\t\t\tconvertedAudio, err := convertRecordedAudio(recordingBuffer.Bytes())\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Fatal(err)\n\t\t\t\t}\n\t\t\t\tanimatingCtx, cancel = context.WithCancel(context.Background())\n\n\t\t\t\tledController.SetLEDs(led.Led{\n\t\t\t\t\tID: 7,\n\t\t\t\t\tG:  255,\n\t\t\t\t}, led.Led{\n\t\t\t\t\tID: 8,\n\t\t\t\t\tG:  255,\n\t\t\t\t})\n\n\t\t\t\tlog.Println(\"Playing recording\")\n\t\t\t\tif err = speaker.Pump(convertedAudio); err != nil {\n\t\t\t\t\tlog.Fatal(err)\n\t\t\t\t}\n\t\t\t\trecording = false\n\n\t\t\t\tledController.SetLEDs(led.Led{\n\t\t\t\t\tID: 7,\n\t\t\t\t\tR:  255,\n\t\t\t\t\tG:  255,\n\t\t\t\t\tB:  255,\n\t\t\t\t}, led.Led{\n\t\t\t\t\tID: 8,\n\t\t\t\t\tR:  255,\n\t\t\t\t\tG:  255,\n\t\t\t\t\tB:  255,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\t// Start recording\n\t\t\t\tlog.Println(\"Now recording\")\n\t\t\t\trecording = true\n\t\t\t\trecordingBuffer.Reset()\n\t\t\t\tgo animateRecording(ledController, animatingCtx)\n\t\t\t\tgo func() {\n\t\t\t\t\terr := mic.Listen(func(audioData []byte) {\n\t\t\t\t\t\trecordingBuffer.Write(audioData)\n\t\t\t\t\t}, animatingCtx)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tif !errors.Is(err, context.Canceled) {\n\t\t\t\t\t\t\tlog.Fatal(err)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t}\n\t\t}\n\t})\n\tdefer btnSub.Cancel()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Keep running forever\n\tselect {}\n}\n\nfunc convertRecordedAudio(data []byte) ([]byte, error) {\n\tlog.Println(\"Converting\", len(data), \"bytes\")\n\tcmd := exec.Command(\"ffmpeg\", \"-f\", \"s24le\", \"-ar\", \"16000\", \"-ac\", \"9\", \"-i\", \"pipe:0\", \"-af\", \"pan=stereo|c0=c0|c1=c1\", \"-f\", \"s16le\", \"-ar\", \"48000\", \"-ac\", \"2\", \"pipe:1\")\n\tcmd.Stdin = bytes.NewReader(data)\n\tvar out bytes.Buffer\n\tcmd.Stdout = \u0026out\n\tcmd.Stderr = os.Stderr\n\tif err := cmd.Run(); err != nil {\n\t\treturn nil, err\n\t}\n\tlog.Println(\"Converted to\", len(out.Bytes()), \"bytes\")\n\treturn out.Bytes(), nil\n}\n\nfunc animateRecording(controller led.Controller, ctx context.Context) {\n\tfor {\n\t\tif ctx.Err() != nil {\n\t\t\treturn\n\t\t}\n\n\t\tcontroller.SetLEDs(led.Led{\n\t\t\tID: 7,\n\t\t\tR:  255,\n\t\t\tG:  255,\n\t\t\tB:  255,\n\t\t}, led.Led{\n\t\t\tID: 8,\n\t\t\tR:  255,\n\t\t\tG:  255,\n\t\t\tB:  255,\n\t\t})\n\n\t\ttime.Sleep(time.Millisecond * 500)\n\n\t\tif ctx.Err() != nil {\n\t\t\treturn\n\t\t}\n\t\tcontroller.SetLEDs(led.Led{\n\t\t\tID: 7,\n\t\t}, led.Led{\n\t\t\tID: 8,\n\t\t})\n\t\ttime.Sleep(time.Millisecond * 500)\n\t}\n}\n\nfunc clearLeds(ledController led.Controller) error {\n\tnumLeds, err := ledController.GetNumLEDs()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tledData := make([]led.Led, numLeds)\n\tfor i := 0; i \u003c numLeds; i++ {\n\t\tledData[i] = led.Led{\n\t\t\tID: i,\n\t\t\tR:  0,\n\t\t\tG:  0,\n\t\t\tB:  0,\n\t\t}\n\t}\n\treturn ledController.SetLEDs(ledData...)\n}\n\n```\n\n## 🤹 CLI\n\nThis project provides a handy cli to perform some routine tasks which is especially useful for debugging.\n\nTo use it, make sure you cloned this repo, ideally in your project folder.\nThen run:\n\n```shell\n$ go run cmd/cli.go\nNAME:\n   EchoGo - Control your echo easily\n\nUSAGE:\n   EchoGo [global options] [command [command options]]\n\nCOMMANDS:\n   boot      Boot your echo\n   shutdown  Shutdown your echo\n   restart   Restart your echo\n   compile   Compile the server app for your echo\n   run       Run the server app on your echo for debugging purposes\n   deploy    Deploy the server app to your echo\n   help, h   Shows a list of commands or help for one command\n\nGLOBAL OPTIONS:\n   --help, -h  show help\n```\n\nHere are some useful tips:\n- Run `go run cmd/cli.go boot` to boot your echo\n- Run `go run cmd/cli.go deploy -c` to compile and deploy the server to the echo\n- Run `go run cmd/cli.go run -c` to compile and run the server to the echo\n\nIf you want to deploy the prebuilt server from GitHub navigate to the [Release page](https://github.com/Binozo/EchoGo/releases) and download the server application to `build/server`.\nThen run:\n```shell\n$ go run cmd/cli.go deploy\n```\n\n\u003e [!NOTE]  \n\u003e If you deploy the server for the first time you need to reboot your echo after a successful deployment. After that no further reboots are required.\n\n## Debugging\n\nHere are some useful commands for debugging the server\n\n- Mount the filesystem read-write: `mount -o rw,remount rootfs /`\n- Pushing the android init script: `adb push echogo.rc /system/etc/init/echogo.rc`\n- Setting right permissions for the init shell script: `adb shell chcon u:object_r:system_file:s0 /data/local/bin/start_server.sh`\n- Disable SELinux: `adb shell setenforce 0`\n- Check for server failures: `adb shell dmesg | grep echogo`\n- Check if SELinux annoys again: `adb shell dmesg | grep \"avc: denied\"`\n- Check server status: `adb shell getprop init.svc.echogo`\n\n## Todo\n- [ ] Make use of `tinymix 61 100` audio control (100 for max volume)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinozo%2Fechogo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbinozo%2Fechogo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinozo%2Fechogo/lists"}