Creating a Factory Reset Daemon for SUSI.AI Smart Speaker

In our constantly evolving SUSI.AI Smart Speaker project, we require regular updates for our devices. And imagine a scenario that during a crucial update, there is a crash or an internet disconnection which stops the SUSI.AI Linux program from booting up. We’ll require a reset method for that. So, we have added a button in SUSI smart speaker that works as a factory reset switch. This daemon was accomplished by using python scripting, bash scripting, and Raspbian’s systemd rules.

Approach followed

We have created a python script that detects the button presses on GPIO port 17. The script is run as soon as the Raspberry Pi is booted using the systemd rules and checks for the device inputs. And if the button press is for more than 7 seconds, the script is run which deletes all the contents of the repo and clones it again.


#! /bin/bash
# To be executed using a physical button

SCRIPT_PATH=$(realpath $0)

cd $DIR_PATH/../..
mv susi_linux/ susi_temp
git clone #while testing change to personal repo
cd susi_linux

rm -rf ../susi_temp



Detecting the Button Press

We have Used the library RPi.GPIO to detect button click on raspberry Pi.

while True:
       if GPIO.input(17) == 1:
       elif GPIO.input(17) == 0 :
           start = time.time()
          while GPIO.input(17) == 0 :
          end = time.time()
           total = end – start
           if total >= 7 :
          else :
               mixer = alsaaudio.Mixer()
               value = mixer.getvolume()[0]
              if value != 0:


If the button press is greater than 7 seconds, factory reset process will start and if the press is less than 7 seconds, the button will function as mute button


Auto Booting The program


For the script to autorun everytime the raspberry pi started. We create systemd file which will allow the program to start as soon as the device has started


Description=SUSI Linux Factory Daemon

ExecStart=/usr/bin/python3 /home/pi/SUSI.AI/susi_linux/factory_reset/



This runs the factory reset script to boot up as soon as the Raspberry Pi starts



susi, factory_daemon, factory_reset, gsoc, gsoc’18,susi_linux , fossasia

Continue Reading Creating a Factory Reset Daemon for SUSI.AI Smart Speaker

Creating a Custom Raspbian Image containing SUSI.AI Linux Libraries

Installing Raspbian and SUSI Linux on your Raspberry Pi can be a long process and if your raspberry Pi crashes due to some bug, you have to repeat the process again and again.

It wastes a lot of valuable time. So, we will discuss a method in which we will have to install the SUSI Linux repo only once and can use it again in case of any issues.

First, we’ll go through the requirements for f installing SUSI Linux on our hardware

Hardware Requirements

1> Raspberry Pi

2> Micro SD card (16GB or greater)

3> USB Mic

4> USB Mouse and USB Keyboard

5> HDMI Monitor

6> ReSpeaker Pi Hat 2 Mic Array(optional)

7> 3.5 mm Jack Headphones / Speaker


Step 1: Preparing SD for Installation

1> To format your SD card

  • You can use softwares like SDCardformater to do so.

2> To install Raspbian

  • Download raspbian official build from here
  • Now mount the Image using software like Etcher or win32diskimager


Step 2: Installing SUSI Linux on your Pi

1> Navigate to the folder `/home/pi` and make a folder called SUSI.AI


cd /home/pi
mkdir SUSI.AI


2> Clone the SUSI Linux repo from here and navigate in the repo


git clone

cd susi_linux/


3> Run the installation script by using the command `./`




4> Run the configuration script by using the following command

`python3 <stt> <tts> <hotword> <wake>`


5> Run SUSI linux with the following command

`python3 -m main`


If it plays a bell after you say ‘SUSI’ , it means that your software has been successfully installed

Step 3: Creating the image

1> Now that you have successfully installed SUSI Linux on your raspberry Pi , we will make a backup of the current stage of the system and use it for future references


2>Turn off the raspberry Pi , and remove the SD card from the Pi and insert it in your system.


3> To create the custom Image , use something like win32 imager and follow the steps below

  • In the text box , create a custom where you want your image to exist
  • Click on read button
  • And voila




Fossasia, gsoc’18, SUSI.AI , susi_linux , gsoc, SUSI HW, installation

Continue Reading Creating a Custom Raspbian Image containing SUSI.AI Linux Libraries

Implementing Volume Action in SUSI Smart Speaker

We all know that a Smart Speaker to excel above its competitors has to excel in first being a good “Speaker” and a speaker has a basic and essential feature which is “volume control”. But things get better if you can control your volume with your voice.

So, we have implemented a feature that allows the user to control the volume of the audio with his/her voice.

Below are the steps we had to follow to implement this feature


Step 1: Creating the Skills

The skills required to implement the ‘volume-action’ is implemented in the SUSI Server repo itself.

The skill is located in



And below are the skills required


set audio volume to *|set audio volume to * percent|set audio volume to * points|set volume to *|set volume to * percent|set volume to * points
!console:Audio volume is now $1$ percent.
{“type”:“audio_volume”, “volume”:$1$}


We get the following response from the server


“actions”: [
       “volume”: “80”,
       “type”: “audio_volume”
       “type”: “answer”,
       “expression”: “Audio volume is now 80 percent.”


Step 2: Finding Volume Action in the server response

Now that our Server responds to our queries regarding the voice change action , we must implement it in our Smart Speaker Client.

We first create a custom class in our in the SUSI API Wrapper repo which has only one member


class VolumeAction(BaseAction):
   def __init__(self , volume):
       self.volume = volume


We check through the actions in the server’s response


elif isinstance(action, VolumeAction):
           result[‘volume’] = action.volume


Step 3: Implementing it in the client

Now to implement the action in our client we use a library called ‘alsaaudio’ to control the master volume of our RaspberryPi


              m = alsaaudio.Mixer()
               os.system(‘play {0} &’.format(self.components.config[‘detection_bell_sound’]))  # nosec #pylint-disable type: ignore                m = alsaaudio.Mixer()
               os.system(‘play {0} &’.format(self.components.config[‘detection_bell_sound’]))  # nosec #pylint-disable type: ignore


Now the user can easily change the speaker using the voice commands




GSoC, GSoC’18, SUSI.AI, SUSI Linux, Smart Speaker , SUSI API Wrapper, SUSI Server, FOSSASIA, Volume Action

Continue Reading Implementing Volume Action in SUSI Smart Speaker

Using a Flask Server to Connect to SUSI smart speaker

A smart speaker becomes significantly smarter when it is connected to a Smart-Phone.

So, we added a way to connect the Smart-Phone to the Smart Speaker and initiate the first way towards a Smart Home.

Use a simple HTTP connection protocol and deploy a light-weight server on the Raspberry Pi to allow connection from a mobile phone.

Step 1: Setting Up the server

Use flask to deploy a light-weight server on the raspberry pi. We’ll install flask using raspbian repos.


1>Install Flask by using the following command

sudo apt-get install python3-flask


2> Setting up the boilerplate code.

Open the terminal and type the following commands


mkdir server_app
cd server_app




Add the following code to your file. This create a server at localhost:5000


from flask import Flask

app = Flask(__name__)

def index():
   return ‘Hello world’

if __name__ == ‘__main__’:, host=‘’)  #This will allow the server to be accessible on all devices


Step 2: Adding Endpoints

Now , add endpoints which will trigger the scripts during initialisation of the raspberry Pi. This will trigger the respective endpoints

def login(auth, email, passwd):
os.system(‘sudo ./ {} {} {}’.format(auth, email,passwd)) #nosec #pylint-disable type: ignore
return ‘Authenticated’ # [email protected](‘/wifi_credentials/<wifissid>/<wifipassd>’)
def wifi_config(wifissid,wifipassd):
wifi_ssid = wifissid
wifi_password = wifipassd
os.system(‘sudo ./home/pi/SUSI.AI/susi_linux/access_point/ {} {}’.format(wifi_ssid,wifi_password))  #nosec #pylint-disable type: ignore
return ‘Wifi Configured’ # pylint-enable


Step 3: Connecting to the endpoints

Now, try and hit the API endpoints to get the response.

eg.As shown in the above example, you will be getting a single line response and will execute a bash script behind the scenes

Now you can access the other endpoints and configure the clients with the SUSI Smart Speaker




fossasia,GSoC,Python, Flask , raspberryPi, SUSI,smart-speaker,FOSSASIA

Continue Reading Using a Flask Server to Connect to SUSI smart speaker

Displaying SUSI Smart speaker under Devices while logging in

The user should be given an ability to access all his devices on one page(Smart Speaker, IOS Device, WebClient and the Android Device). The user was previously allowed to access his/her web app account, the IOS app, Android App. But not the Smart Speaker. Now, this feature will allow the user to easily manage the Smart Speaker devices without many hassles.

In this post, we will be talking about the API’s that we have used to send the details of the Smart-Speaker to the server.

About the API’s

  1. Below is the API endpoint which will return the list of all devices present under the user’s account

We use the following endpoint



Below is sample response :

“devices”: {
“8C-39-45-cc-eb-95”: {
“name”: “Device 1”,
“room”: “Room 1”,
“geolocation”: {
“latitude”: “52.34567”,
“longitude”: “62.34567”


  1. The second endpoint that we will be using is to add a new Device under the devices section

API Endpoint



This endpoint has the following parameters

  • macid (Mac address of the device)
  • name (Name of the device)
  • room (Room info of the device)
  • latitude (Latitude info of the device)
  • longitude (Longitude info of the device)


After successfully hitting the endpoint , you’ll get the following response


“accepted”: true,
“message”: “You have successfully added the device!”,
“session”: {“identity”: {
“type”: “email”,
“name”: [email protected],
“anonymous”: false


Implementing the API’s

  1. First, we check the server for existing devices. This step is implemented primarily to check weather our current Smart Speaker is already configured or not.
get_device_info = api_endpoint + ‘/aaa/listUserSettings.json?’

param1 = {

   # print(access_token)

   if access_token is not None:
       device_info_response = requests.get(get_device_info,param1)
       device_info = device_info_response.json()

   # print(device_info)

If the current device is not already configured on Server, we proceed to next step.

  1. Now we will configure the device with the server and then post the device settings there.
    We will implement the API in the following way:


if device_info is not None:
   device = device_info[‘devices’] # list of existing mac ids
   session = device_info[‘session’] # session info
   identity = session[‘identity’]
   name = identity[‘name’]
   params2 = {
   ‘macid’: macid,
   ‘name’: name,
   ‘device’: ‘Smart Speaker’,
   ‘access_token’: access_token

   for dev in device:
       if dev == macid:
           print(‘Device already configured’)
       else :
           adding_device =, params2)


To extract the mac address from the speaker and pass it as the params , we use a python library called UUID and this is how SUSI Smart Speaker is displayed on the web client(




Continue Reading Displaying SUSI Smart speaker under Devices while logging in

Creating an Update Daemon for SUSI Smart Speaker

A daemon in reference of operating systems is a computer program that runs as a background process rather than under direct control of the user. Various daemons are being used in SUSI smart speaker.

The following daemons have been created

  • Update Daemon
  • Media Discovery Daemon
  • Factory Reset Daemon 

In this blog, we’ll be discussing the implementation of the Update Daemon in SUSI.AI

Update Daemon

Due to the ever-growing coding community, it is needed to provide regular updates to the smart speaker and keep it in sync with the latest technology. Hence an Update Daemon was required that could fetch updates at a regular interval.

The Updated Daemon was implemented in the following steps

1.Deciding the Update Interval

How frequently should we check for updates was the first question that was tackled while implementing this daemon.
We decided that we should check for Update, every time the Raspberry Pi starts and an internet connection was available.

2. Implementing The Decision

To start the Update script every time the Raspberry Pi starts, we decided to create Systemd rules.

Description=Update Check- SUSI Linux



The above rule waits for a network connection to be established with the Raspberry Pi and then triggers a bash script that fetches updates

3. Fetching The Updates

Now, a bash script was prepared that would fetch the latest changes from the online repo and merge the latest changes in the local repo



LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse “$UPSTREAM”)
BASE=$(git merge-base @ “$UPSTREAM”)
if [ $LOCAL = $REMOTE ]
   echo “Up-to-date”
elif [ $LOCAL = $BASE ]
   echo “Need to pull”
   echo “Diverged”

if [$CHECK = “Need-to-pull”]
   git fetch UPSTREAM
   git merge UPSTREAM/master



Tags, gsoc, gsoc’18, fossasia, update, daemon, update_daemon, smart speaker, systemd, hardware

Continue Reading Creating an Update Daemon for SUSI Smart Speaker

Create a Wireless Access Point Using a Raspberry Pi to Connect with SUSI Smart Speaker

To use the pi as a wifi bridge, a local network or just as a wifi range extender.We at FOSSASIA are using it as a network to connect between our SUSI.AI smart speaker and the Android and IOS devices. Or maybe because you can !! :’)


  1. Raspberry Pi Model 3(since we will be using an internal wifi)
  2. Power supply for the Pi.
  3. Monitor (optional)
  4. Keyboard (optional)
  5. Mouse (optional)


1.Install and upgrade raspbian


Sudo apt-get update && sudo apt-get install


2. Install hostapd and dnsmasq .
This will allow us to use our raspberry pi as a wireless access point


apt-get remove –purge hostapd -yqq
apt-get update -yqq
apt-get upgrade -yqq
apt-get install hostapd dnsmasq -yqq


3. Now we will add broadcasting IP and DNS address in the dnsmasq configuration file

To access the configuration file use:

sudo nano /etc/


And to the bottom of the file, add the following commands




  1. Now to select the SSID and the PASSWORD for the access point, we’ll need to change the configurations of hostapd package
sudo nano /etc/hostapd/hostapd.conf


Then, use the following commands :




  1. To finally sum up the configuration, we’ll have to create a  custom network interface that combines all the settings that we have made.
sudo nano /etc/network/interfaces


And add the following lines it the EOF

allow-hotplug wlan0
iface wlan0 inet static


Now, we just have to have to disable default interfaces so that they do not interfere with the custom interfaces that we have made.

To do so


sudo nano /etc/dhcpcd.conf


Add the following line at the end of the file

denyinterfaces wlan0


  1. Now just restart the services


systemctl enable hostapd && systemctl enable dnsmasq

sudo service hostapd start && sudo service dnsmasq start

sudo reboot


Now, you will be able to enjoy a self-made access point which is used as a basic mode of connection in SUSI Smart Speaker and can also be used in various other access point methods.






Continue Reading Create a Wireless Access Point Using a Raspberry Pi to Connect with SUSI Smart Speaker

Adding Audio Streaming from Youtube in SUSI Linux

In this blog post we will describe how the youtube streaming works in the

SUSI smart speaker and how audio is streamed directly from youtube videos.

To achieve this process, we have used an amazing Open-Source project called MPV music Player along with python libraries like Subprocess.

1.Processing a Query to the server

Firstly , the user asks the smart speaker to play the youtube audio by simply adding a ‘play’ word before his/her favorite song. eg. I’ll say ‘play despacito’ and then the command is recognized and a query is sent to the server which sends the following response as a JSON object.

“actions”: [
       “type”: “answer”,
       “expression”: “Playing Luis Fonsi – Despacito ft. Daddy Yankee”
       “identifier”: “kJQP7kiw5Fk”,
       “identifier_type”: “youtube”,
       “type”: “video_play”

2.Parsing the response

Then the speaker parses the response in the following way.

The Speaker traverses through all the actions returned in the response and checks for all the “identifier” by assigning a custom class to it.

class VideoAction(BaseAction):
   def __init__(self, identifier , identifier_type):
       self.identifier = identifier
       self.identifier_type = identifier_type

Now we check whether the query is the type of a custom class VideoAction and then the client processes the query as the response.

      elif isinstance(action, VideoAction):
          result[‘identifier’] = action.identifier
           audio_url = result[‘identifier’]  

3.Implementing the Actions

Now that we have identified that the response contains a Video Action, we can finally implement a way to play the audio from the URL.
We use a music player called MPV Music Player and the library Subprocess to make it run asynchronously.

if ‘identifier’ in reply.keys():
   classifier = reply[‘identifier’]
   if classifier[:3] == ‘ytd’:
       video_url = reply[‘identifier’]
       video_pid = subprocess.Popen(‘mpv –no-video{} –really-quiet &’.format(video_url[4:]), shell=True)  # nosec #pylint-disable type: ignore
       self.video_pid =

This is how audio is streamed from youtube videos in SUSI Smart Speaker.




fossasia, gsoc’18, susi,, youtube, music, mp3 , mpv, audio stream


Continue Reading Adding Audio Streaming from Youtube in SUSI Linux

Adding Offline support To SUSI Linux

Till now, SUSI smart speaker was working only as an online model like the other speakers in the market. For the first time, we have introduced a feature which allows the speaker to work offline. We deployed the server on the hardware itself and also provide the option of an online server as a fallback.


The Offline Support was implemented in the following steps


Step 1: Deploying SUSI Server Locally


Firstly , configure a bash script to allow automatic deployment of the server along with the initialization of the susi_linux script.


echo “Deploying local server”
if  [ ! -e “susi-server” ]
   git clone

if [ -e “susi_server” ]
   cd susi_server
   git submodule update –recursive –remote
   git submodule update –init –recursive
   ./gradlew build


The above builds the server and deploys it on ‘localhost:4000’.


Then, add the following test on SUSI Linux wrapper to check if the local server is up and running. Using the local server not adds an offline support but also increases the efficiency by around 30%.

def check_local_server():
   test_params = {
       ‘q’: ‘Hello’,
       ‘timezoneOffset’: int(time.timezone / 60)
       chat_url = ‘http://localhost:4000/susi/chat.json’
       if (requests.get(chat_url, test_params)):
           print(‘connected to local server’)
           global api_endpoint
           api_endpoint = ‘http://localhost:4000’
   except requests.exceptions.ConnectionError:
       print(‘local server is down’)



As shown above, this is a test checking for the local server. If the local server is down, the online server is chosen as a fallback


Step 2: Adding an Offline STT Service

Now, that we are able to process a query offline. We must have a way in which, we can recognize the user’s voice commands without using the internet. For that, we use the service of PocketSphinx. But first, we check if the internet is available or not


def internet_on():
           urllib2.urlopen(‘’, timeout=1)  # nosec #pylint-disable type: ignore
           return True  # pylint-enable
       except urllib2.URLError as err:
           return False


If the internet connection is available, we use the online STT service which is Google STT ( default) and switch over to PocketSphinx in case the internet connection is not available.


Step 3: Adding the Offline TTS service

Finally, we’ll need an offline TTS service which will help us turn SUSI’s response to voice commands. We’ll be using a service called flite TTS as our offline TTS.


elif payload == ‘ConnectionError’:
            self.notify_renderer(‘error’, ‘connection’)                                  self.notify_renderer(‘error’, ‘connection’)
            config[‘default_tts’] = ‘flite’
            os.system(‘play extras/connect-error.wav’)              


We check if there is a ConnectionError, and then we switch to flite TTS after play an error query


Final Output:

We now get a Smart Speaker which is functional without any internet connection.





Fossasia, susi, gsoc, gsoc’18, offline_tts , offline_stt ,flite , pocketsphinx

Continue Reading Adding Offline support To SUSI Linux

Creating a Media Daemon for SUSI Smart Speaker

A daemon in reference of operating systems is a computer program that runs as a background process rather than under direct control of the user. Various daemons are being used in SUSI smart speaker.

The following features have been created

  • Update Daemon
  • Media Discovery Daemon
  • Factory Reset Daemon

In this blog, we’ll be discussing the implementation of the Media Discovery Daemon

Media Discovery Daemon:

The SUSI Smart speaker will have an essential feature which will allow the Users to play music from their USB devices. Hence , a media daemon will be running which will detect a USB connection and then scan it’s contents checking for all the mp3 files and then create custom SUSI skills to allow SUSI Smart Speaker to play music from your USB device.


The Media Daemon was implemented in the following steps

1.UDEV Rules

We had to figure out a way to run our daemon as soon as the user inserted the USB storage and stop the daemon as soon as the USB storage was removed


So, we used UDEV rules to trigger the Media Daemon.


ACTION==“add”, KERNEL==“sd?”, SUBSYSTEM==“block”, ENV{ID_BUS}==“usb”, RUN=“/home/pi/SUSI.AI/susi_linux/media_daemon/”ACTION==“remove, KERNEL==“sd?”, SUBSYSTEM==“block”, ENV{ID_BUS}==“usb”, RUN=“/home/pi/SUSI.AI/susi_linux/media_daemon/”

The Udev rules trigger a script called ‘’  on USB detection and a script called ‘’ on USB removal.

2. Custom Skill Creation

As the USB connection is now detected ,a script is triggered which checks the presence of a  local SUSI server in the repo. If a local server instance is detected,a python script is triggered which parses through the USB mount point and checks for the list of mp3 files present in the storage device and then create a custom skill file in the local server instance.


media_daemon_folder = os.path.dirname(os.path.abspath(__file__))
base_folder = os.path.dirname(media_daemon_folder)
server_skill_folder = os.path.join(base_folder, ‘susi_server/susi_server/data/generic_skills/media_discovery’)
server_settings_folder = os.path.join(base_folder, ‘susi_server/susi_server/data/settings’)

def make_skill(): # pylint-enable
   name_of_usb = get_mount_points()
   x = name_of_usb[0]
   USB = name_of_usb[0]
   mp3_files = glob(“*.mp3”)
   f = open( media_daemon_folder +‘/custom_skill.txt’,‘w’)
   music_path = list()
   for mp in mp3_files:
       music_path.append(“{}”.format(USB[1]) + “/{}”.format(mp))

   song_list = ” “.join(music_path)
   skills = [‘play audio’,‘!console:Playing audio from your usb device’,‘{“actions”:[‘,‘{“type”:”audio_play”, “identifier_type”:”url”, “identifier”:”file://’+str(song_list) +‘”}’,‘]}’,‘eol’]
   for skill in skills:
       f.write(skill + ‘\n’)
   shutil.move( media_daemon_folder + ‘custom_skill.txt’, server_skill_folder)
   f2 = open(server_settings_folder + ‘’,‘a’)
   f2.write(‘local.mode = true’)

def get_usb_devices():
   sdb_devices = map(os.path.realpath, glob(‘/sys/block/sd*’))
   usb_devices = (dev for dev in sdb_devices
       if ‘usb’ in dev.split(‘/’)[5])
   return dict((os.path.basename(dev), dev) for dev in usb_devices)

def get_mount_points(devices=None):
   devices = devices or get_usb_devices() # if devices are None: get_usb_devices
   output = check_output([‘mount’]).splitlines() #nosec #pylint-disable type: ignore
   output = [tmp.decode(‘UTF-8’) for tmp in output ] # pytlint-enable
   def is_usb(path):
       return any(dev in path for dev in devices)
   usb_info = (line for line in output if is_usb(line.split()[0]))
   return [(info.split()[0], info.split()[2]) for info in usb_info] 


Now a custom skill file will be created in the local server instance by the name of `custom_skill.txt` and the user can play audio from USB by speaking the command ‘play audio’


3. Preparing for the Next USB insertion

Now if the User wants to update his/her music library or wants to use another USB storage device. The USB will be removed and hence the custom skill file is also deleted from the script ‘’ which is triggered via the UDEV rules

#! /bin/bash

SCRIPT_PATH=$(realpath $0)

cd $DIR_PATH/../susi_server/susi_server/data/generic_skills/media_discovery/

sudo rm custom_skill.txt  


This is how the Media Discovery Daemon works in SUSI Smart Speaker




gsoc, gsoc’18 , fossasia,, smart speaker, media daemon, susi skills

Continue Reading Creating a Media Daemon for SUSI Smart Speaker