[PYTHON] Get Android notifications to speak slowly

Using the Android app Macrodroid and Raspberry pi, the voice slowly speaks the notification of the smartphone. I made a system.

Overview

Macrodroid is an application that can automate tasks on Android. Various actions can be automatically executed triggered by some event on Android.

Link this with a simple web server set up on Raspberry Pi, and when a notification comes, send the content to the web server and send the voice with AquesTalkPi. Output.

environment

Raspberry Pi side settings

If you are using Raspberry Pi, you may need to replace the SD card to recreate the environment. In such a case, if you have a Dockerfile, you don't have to remember how to build an environment.

So I will run a simple web server with Docker. (Although Docker seems to be exaggerated because there is almost no code amount this time)

The Dockerfile created this time is as follows.

Dockerfile


FROM balenalib/rpi-raspbian:buster

RUN apt-get update && \
    apt-get -y install --no-install-recommends  alsa-utils python3 && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# https://www.a-quest.com/products/aquestalkpi.After reading the html program license agreement, download the following
RUN mkdir /root/bin && \
    curl -kL "https://www.a-quest.com/cgi-bin/download.php?download=1&readed=yes" -o /tmp/aquestalk.tgz && \
    tar xzvf /tmp/aquestalk.tgz -C /tmp && \
    mv /tmp/aquestalkpi/AquesTalkPi /root/bin && \
    mv /tmp/aquestalkpi/aq_dic /root/bin && \
    rm /tmp/aquestalk.tgz && rm -r /tmp/aquestalkpi
ADD ./softalk_server.py /root/bin

EXPOSE 8000
CMD ["python3", "/root/bin/softalk_server.py"]

Also, the simple web server was run on Python.

softalk_server.py


# -*- coding:utf-8 -*-
from http.server import HTTPServer, SimpleHTTPRequestHandler
from urllib import parse
import subprocess
KEYS = ["app", "title", "message"]


#Have the text speak slowly to the voice
def talk(text):
    p1 = subprocess.Popen(
        ["/root/bin/AquesTalkPi", text],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
    )
    p2 = subprocess.Popen(
        ["aplay"],
        stdin=p1.stdout, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT
    )
    p1.stdout.close()  # SIGPIPE if p2 exits.
    p2.communicate()[0]


# [app, title, messa]Dictionary text consisting of the keys of_Based on dic
#Prepare an utterance message
def format_message(text_dic):
    if text_dic['title'] is None:
        return None
    if text_dic['message'] is None:
        return None

    if len(text_dic['message']) < 40:
        formatted = '{app}From{title}The message is titled.{message}'.format(
            **text_dic
        )
    else:
        formatted = '{app}From{title}The message is titled.'.format(
            **text_dic
        )
    return formatted


#Simple web server
#When you receive a GET request, based on that parameter
#Play the voice slowly from the speaker
class RequestHandler(SimpleHTTPRequestHandler, object):
    def do_GET(self):
        query = parse.urlparse(self.path).query
        query_dic = parse.parse_qs(query)
        self.send_response(200)
        for key in KEYS:
            if key not in query_dic:
                query_dic[key] = None
            else:
                query_dic[key] = query_dic[key][0]
        print('query = {}'.format(query_dic))
        formatted = format_message(query_dic)
        #GET request parameters are expected
        #If not, formatted is None and no audio is played
        if formatted is not None:
            talk(formatted)
        self.end_headers()


if __name__ == '__main__':
    text = 'The notification server has started'
    talk(text)

    httpd = HTTPServer(("", 8000), RequestHandler)
    httpd.serve_forever()

Then run the following command in the directory where Dockerfile and softalk_server.py are located.

$ docker build -t softalk_notification .
$ docker run -d --name notification_server --device /dev/snd -p 8000:8000 --restart=always softalk_notification

By adding the option --restart = always, it is convenient to automatically rebuild the container even when it is restarted (even when the docker daemon is stopped).

It also passes dev / snd to --device to play the speaker sound using ALSA.

In addition, the web server port is set to 8000 for both the container and the host.

If all goes well, the next GET request should speak slowly.

$ curl localhost:8000 --get --data-urlencode 'app=slowly' --data-urlencode 'title=test' --data-urlencode 'message=slowlyしていってね'

Android side settings

Next, let's make a GET request to the web server when the notification comes to Android. This can be achieved with Macrodroid.

After installing Macrodroid from Google Play, create the following macro.

--Trigger --Tap "Device Events"> "Notifications" --"When notification is displayed"> "Any app"> Tap OK (in some cases, it is necessary to set permissions for the notification area)

--Action --Tap "Applications"> "Open Website / HTTP GET" --Check "Encoding parameter URL" --Enter the URL ʻEnter the following in the part (when the IP address of Raspberry Pi is 192.168.0.2) and tap ʻOK at the bottom right

URL


192.168.0.2:8000?app=[not_app_name]&title=[not_title]&message=[notification]

After setting the trigger and action, tap the check mark at the bottom right of the screen. Please enter the category and macro name appropriately.

Setup is completed.

in conclusion

This time it is the minimum setting, so I think that fine adjustment is necessary for practical use. The following are the setting items that come to mind at present.

--Do you read the notifications of all apps?: Can be specified to some extent on the Macrodroid side --Do you always read aloud: Macrodroid time trigger (it seems interesting to judge by brightness in combination with Nature remo)

If you are interested, why not give it a try.

Recommended Posts

Get Android notifications to speak slowly
Push notifications from Python to Android using Google's API
First get used to sending