OpenWRT. Make your router shout

Recently @vshymanskyy has kindly been able to create a script in LUA capable of running fluently on OpenWRT machines.

Although I am a newcomer, I have dared to undertake a project that handles a bare OpenWRT router. “Bare” means that the router is the final device, without Arduino, ESP8266 or anything like that. In fact, what is intended here is to run certain processes on the router by triggering them from the app.

Basically, the usage flow of the app is

  1. Write a text. It will immediately be sent to the router. A text-to-voice process is launched on the router and an audio file is generated.
  2. Slide the volume selector. A new process is launched on the router and the volume of the audio device is set.
  3. Press the “SHOUT!” button. A final process plays the audio file.

To accomplish this task it is required a router equipped with USB, to which an audio dongle is connected. Then some packages have to be installed on the router.

opkg update && opkg install kmod-usb-audio alsa-utils svox

Try these commands to check your router is ready:

    # Generate an audio file
    pico2wave -w /tmp/voz.wav -l en-US "This command will generate an audio file in american English."
    # Set volume to 50%
    amixer set Headphone 50%
    # Play the audio file
    aplay -q -f S16_LE -D plughw:0,0 /tmp/voz.wav

Of course to hear something, an audio dongle must be plugged in.

Now, it’s time for the sketch (that is not really a sketch but a lua script).

    local socket = require("socket")
    local use_ssl, ssl = pcall(require, "ssl")

    local Blynk = require("blynk.socket")
    local Timer = require("timer")

    assert(#arg >= 1, "Please specify Auth Token")
    local auth = arg[1]

    local blynk = Blynk.new(auth, {
      heartbeat = 10, -- default h-beat is 30
      --log = print,
    })

    local function connectBlynk()
      local host = "blynk-cloud.com"

      local sock = assert(socket.tcp())
      sock:setoption("tcp-nodelay", true)

      if use_ssl then
        print("Connecting Blynk (secure)...")
        sock:connect(host, 8441)
        local opts = {
          mode = "client",
          protocol = "tlsv1"
        }
        sock = assert(ssl.wrap(sock, opts))
        sock:dohandshake()
      else
        print("Connecting Blynk (tcp)...")
        sock:connect(host, 80)
      end

      -- tell Blynk to use this socket
      blynk:connect(sock)
    end

    blynk:on("connected", function(ping)
      print("Ready. Ping: "..math.floor(ping*1000).."ms")
    end)

    blynk:on("disconnected", function()
      print("Disconnected.")
      -- auto-reconnect after 5 seconds
      socket.sleep(5)
      connectBlynk()
    end)

    -- text to wav
    blynk:on("V0", function(param)
      os.execute("pico2wave -w /tmp/voice.wav -l en-US "..[["]]..tostring(param[1])..[["]])
      --[[ for other languages, replace the above en-US string.
        Available languages are,
           en-GB  (British English)
           de-DE  (German)
           es-ES  (Spanish)
           fr-FR  (French)
           it-IT  (Italian)
        ]]
    end)

    -- set volume value 0 .. to 151
    blynk:on("V1", function(param)
      os.execute("amixer -q set Headphone "..[["]]..tostring(param[1])..[["]])
    end)


    -- push to shout
    blynk:on("V2", function(param)
      if tonumber(param[1]) == 1 then
        os.execute("aplay -q -f S16_LE -D plughw:0,0 /tmp/voice.wav")
        blynk:virtualWrite(2, 0)
      end
    end)

    connectBlynk()

    while true do
      blynk:run()
    end

Have fun!

3 Likes

Very cool. Thanks for sharing!

1 Like