⬆ Level up

Rhasspy Shopping list skill

Features

Things it cannot do

Missing features I have on the radar

Changelog

Downloads

Program flow

Prerequisites

Installation instructions

I will not elaborate a lot on this as it can become a complex topic. In a nutshell: Back to the main road:
  1. Import the *.sql file into the database you just created.
  2. Go to the table storeTypes and create entries for the shops you usually visit, like discounter, hardware stores, etc.. This will essentially group the resulting shopping list into blocks for each of those storeTypes.
  3. Go to the table products and create as many entries as you want. Each product is also linked with a storeType where you usually purchase the item.
  4. Go to Rhasspy and create a slot named "shoppingProduct". It needs to contain entries for all the products you just created. I'd recommend to use synonyms to make it more user-friendly (see below Syntax for the slot "shoppingProduct").
  5. You'll need to run the scripts provided above at the corresponding event. In my case my home automation software checks a directory if a script by the name of the "[SentenceName]" exists. If so it'll be executed. Hence the four scripts. How you get them executed in your environment is a problem you may have your own solution for. If not feel free to use mine
  6. The application will return 0 for succesful executions, a higher value for errors. Your way of execution scripts needs to give audible or visible feedback.

Examples for sentences

English

[ShoppingListAdd]
(add|put|write) ($shoppingProduct){shoppingProduct} (on|to|onto) (shopping list|grocery list|buying list)
buy ($shoppingProduct){shoppingProduct}
(add|put|write) (0..10000){shoppingAmount} [($shoppingUnit){shoppingUnit}] ($shoppingProduct){shoppingProduct} (on|to|onto) (shopping list|grocery list|buying list) [hinzu]

[ShoppingListRemove]
(take|remove|delete) ($shoppingProduct){shoppingProduct}  [off] [from] (shopping list|grocery list|buying list)
(take|remove|delete) (0..10000){shoppingAmount} [($shoppingUnit){shoppingUnit}] ($shoppingProduct){shoppingProduct}  [off] [from] (shopping list|grocery list|buying list)

[ShoppingListSend]
(send|distribute) (shopping list|grocery list|buying list)

[ShoppingListReset]
(create new|reset|delete|empty) (shopping list|grocery list|buying list)

German

[ShoppingListAdd]
(füge|setze|schreibe) ($shoppingProduct){shoppingProduct} (zur|auf die|auf den|vom) (Einkaufsliste|Einkaufszettel|Liste|Zettel) [hinzu]
($shoppingProduct){shoppingProduct} (zur|auf die|auf den) (Einkaufsliste|Einkaufszettel|Liste|Zettel) [(setzen|hinzufügen|schreiben|aufschreiben)]
($shoppingProduct){shoppingProduct} kaufen
(füge|setze|schreibe) (0..10000){shoppingAmount} [($shoppingUnit){shoppingUnit}] ($shoppingProduct){shoppingProduct} (zur|auf die|auf den|vom) (Einkaufsliste|Einkaufszettel|Liste|Zettel) [hinzu]
(0..10000){shoppingAmount} [($shoppingUnit){shoppingUnit}] ($shoppingProduct){shoppingProduct} (zur|auf die|auf den) (Einkaufsliste|Einkaufszettel|Liste|Zettel) [(setzen|hinzufügen|schreiben|aufschreiben)]
(0..10000){shoppingAmount} [($shoppingUnit){shoppingUnit}] ($shoppingProduct){shoppingProduct} kaufen

[ShoppingListRemove]
(streiche|entferne|nehme) ($shoppingProduct){shoppingProduct} von (dem|der) (Einkaufsliste|Einkaufszettel|Liste|Zettel)
($shoppingProduct){shoppingProduct} von (dem|der) (Einkaufsliste|Einkaufszettel|Liste|Zettel) (streichen|entfernen|nehmen)
(streiche|entferne|nehme) (0..10000){shoppingAmount} [($shoppingUnit){shoppingUnit}] ($shoppingProduct){shoppingProduct} von (dem|der) (Einkaufsliste|Einkaufszettel|Liste|Zettel)
(0..10000){shoppingAmount} [($shoppingUnit){shoppingUnit}] ($shoppingProduct){shoppingProduct} von (dem|der) (Einkaufsliste|Einkaufszettel|Liste|Zettel) (streichen|entfernen|nehmen)

[ShoppingListSend]
(Einkaufsliste|Einkaufszettel|Liste|Zettel) (verschicken|senden|versenden)
(verschicke|sende) (Einkaufsliste|Einkaufszettel|Liste|Zettel)

[ShoppingListReset]
(Einkaufsliste|Einkaufszettel|Liste|Zettel) (zurücksetzen|löschen|leeren|leer machen)
(Leere|Leeren|Neue|Neuen) (Einkaufsliste|Einkaufszettel|Liste) [erstellen|anfangen]
Setze (Einkaufsliste|Einkaufszettel|Liste|Zettel) zurück

Syntax for the slot "shoppingProduct":

I'd recommend to use synonyms, also for singular and plural of the same item: (tissues|tissue|handkerchiefs|handkerchief):tissues

Important here is that the value at the end is the one under which the program will identify the entry in the database, so here "tissues" needs to be the product name in the DB.

Then go to sentences and add something that works with your language. Important is that there are 4 main actions to be distinguished. Also where applicable there's the shoppingProduct slot created above.

Use slot_programs

Instead of maintaining a list in the database and another one in Rhasspy you can use the Rhasspy feature slot_programs: https://rhasspy.readthedocs.io/en/latest/training/#slot-programs

To automatically get the values for shoppingProducts you can utilize the shoppingList.php from the downloads section.
Because most people seem to have Rhasspy running as a Docker container with limited linux functionality inside I decided to use curl. Put an (executable) bash script named shoppingProduct in the folder with this content:

#!/bin/bash

curl http://myWebserverAddress/shoppingList.php?command=printRhasspyProductList

Import values

If you decide to use a regular slot file with text content (rather than the slot_programs-method described above) you can put all your words into a text file and import it with java -jar ShoppingList.jar --action importProducts --filePath absolutePathToFile
Duplicate products are skipped. Synonyms are working if entered as described above.

Example values for the slot "shoppingProduct":

(remember to add those to the database, only the main word of each line)

English

		(tissues|handkerchiefs):tissues
		soy sauce
		tomatoes
		wine
		Mascarpone
		apples
		cream
		ground meat
		coffee
		salmon
		juice
		olives
		peanut butter
		(jam|jelly):jam
		cottage cheese
		yoghurt
		mushrooms
		oranges
		Kardamom
		potatoes
		sour cream
		gouda
		onions
		salad
		coke
		leek
		rice
		bread rolls
		eggplants
		candles
		ketchup
		ayran
		nutella
		(pepper white|white pepper):pepper white
		milk
		pickles
		vinegar
		noodles
		cayenne pepper
		bananas
		flowers
		vanilla sugar
		mustard
		(feta cheese|feta):feta cheese
		shower gel
		spices
		zuchini
		orange juice
		hazelnuts
		bread
		water
		carots
		peas
		peppers
		tomato sauce
		apple juice
		honey
		beer
		salat dressing
		olive oil
		sugar
		liquid soap
		raspberries
		garlic
		kidney beans
		ice cream
		baking powder
		shampoo
		cereals
		flours
		corn
		soap
		toast
		lenses
		cheese
		chocolate
		pepperoni
		baguette
		toilet paper
		beans
		grape juice
		plants
		batteries
		cream cheese
		

German

		(Tempos|Taschentücher):Tempos
		Sojasauce
		Tomaten
		Wein
		Mascarpone
		Äpfel
		Sahne
		Hackfleisch
		Kaffee
		Lachs
		Saft
		Humus
		Oliven
		Erdnussbutter
		Alkoholfreies Weizen
		Marmelade
		Badputzmittel
		Hüttenkäse
		Joghurt
		Pilze
		Orange
		Kardamom
		Kartoffeln
		Saure Sahne
		Gouda
		Zwiebeln
		Haferflocken
		Salat
		Cola
		Quark
		Streukäse
		Lauch
		Tomatenmark
		Reis
		Brötchen
		Auberginen
		Kerzen
		Ketchup
		Ayran
		Schokoguss
		Nutella
		(Pfeffer weiß|weißer Pfeffer|weißen Pfeffer):Pfeffer weiß
		Scheuermilch
		Leinsamen
		Milch
		Gurke
		(Essig|Branntweinessig):Essig
		Waldbeeren
		Nudeln
		Nektarinen
		Cayennepfeffer
		Bananen
		Blumen
		Vanillezucker
		Senf
		(Harzerkäse|Stinkekäse):Harzerkäse
		Schafskäse
		Duschgel
		Gewürze
		Zucchini
		(Orangensaft|Osaft):Orangensaft
		Haselnüsse
		Kichererbsen
		Milchreis
		Brot
		Wasser groß
		Karotten
		Erbsen
		Paprika
		Schmand
		Gelatine
		Raclettekäse
		Deo
		Lätta
		Tomatensauce
		Zewa
		Frühlingszwiebeln
		Apfelsaft
		Honig
		Bier
		Salatdressing
		Mohrenköpfe
		Olivenöl
		Gemüsebrühe
		Zucker
		Wasser
		Flüssigseife
		Puderzucker
		(Tiefkühlgemüse|TK Gemüse):Tiefkühlgemüse
		Putzmittel
		Himbeeren
		Grießbrei
		Knoblauch
		Kidneybohnen
		Gurken
		Eis
		Backpulver
		Vollkornbrot
		Shampoo
		(Mottenfallen|Mottenfalle):Mottenfallen
		(Geschredderte Tomaten|Tomaten stückig):Tomaten stückig
		Müsli
		Mehl
		Mais
		Seife
		Skyr
		Toast
		Linsen
		(Baumarkt|Bauhaus|Obi):Baumarkt
		Margerine
		Käse
		Schokolade
		Desinfektionsmittel
		Pepperoni
		Baguette
		Klopapier
		Wasser klein
		Eiweißbrot
		Bohnen
		Kloputzmittel
		Traubensaft
		Puddingpulver
		Pflanzen
		(Pfeffer schwarz|Pfeffer|schwarzer Pfeffer|schwarzen Pfeffer):Pfeffer schwarz
		Tütensuppe
		Batterien
		(Nähgarn|Garn):Nähgarn
		Frischkäse
		

Database updates

The version is written in the table "settings". If this table does not exist, yet you have version 1.
Please execute all commands one after another including all version steps you may be taking (if you're going from 1 to 3 execute steps for versions 2 + 3).

For database version 2 (program version 4)

ALTER TABLE `products` ADD `synonyms` VARCHAR(500) NULL DEFAULT NULL COMMENT 'Separate entries with semicolons.' AFTER `name`;
CREATE TABLE `shoppingList`.`settings` ( `settingName` VARCHAR(100) NOT NULL , `settingValue` VARCHAR(100) NOT NULL , PRIMARY KEY (`settingName`)) ENGINE = InnoDB; 
INSERT INTO `settings` (`settingName`, `settingValue`) VALUES ('databaseVersion', '2') 

For database version 3 (program version 6)

CREATE TABLE `units` (`id` int(11) NOT NULL, `name` varchar(100) NOT NULL, `abbreviation` varchar(10) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `units` ADD PRIMARY KEY (`id`);
ALTER TABLE `units` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE `listEntries` ADD `amount` FLOAT NOT NULL AFTER `productId`, ADD `unit` INT NOT NULL AFTER `amount`;
INSERT INTO `units` (`id`, `name`, `abbreviation`) VALUES (NULL, 'piece', 'pc');
UPDATE listEntries SET listEntries.amount=1, listEntries.unit=1;
ALTER TABLE `listEntries` ADD FOREIGN KEY (`unit`) REFERENCES `units`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE `listEntries` CHANGE `amount` `amount` FLOAT NOT NULL DEFAULT '1';
ALTER TABLE `units` ADD `isDefault` TINYINT(2) NOT NULL DEFAULT '0' AFTER `abbreviation`;
ALTER TABLE `listEntries` DROP PRIMARY KEY, ADD PRIMARY KEY( `listId`, `productId`, `unit`);
ALTER TABLE `units` ADD `isDummy` TINYINT(2) NULL DEFAULT '0' COMMENT 'This unit will not actually be displayed. Instead an item will just be shown without amount or unit.' AFTER `isDefault`;
ALTER TABLE `units` CHANGE `isDummy` `isDummy` TINYINT(2) NOT NULL DEFAULT '0' COMMENT 'This unit will not actually be displayed. Instead an item will just be shown without amount or unit.';
ALTER TABLE `units` ADD `isPiece` TINYINT(2) NOT NULL DEFAULT '0' AFTER `isDummy`;
ALTER TABLE `listEntries` DROP FOREIGN KEY `listEntries_ibfk_3`; ALTER TABLE `listEntries` ADD CONSTRAINT `listEntries_ibfk_3` FOREIGN KEY (`unit`) REFERENCES `units`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE `listEntries` DROP FOREIGN KEY `listEntries_ibfk_2`; ALTER TABLE `listEntries` ADD CONSTRAINT `listEntries_ibfk_2` FOREIGN KEY (`productId`) REFERENCES `products`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
UPDATE `settings` SET `settingValue`='3' WHERE `settingName`='databaseVersion';