In Acts 8 verses 36-39, some woman called Dorcas falls ill and dies, and then rises again. No worshippers for her, just more thankless life. Thanks God! Anyhow, Dorcas is the name of the second incarnation of this stupid talking Creepy Urchin thing at Nottingham Hackspace.
Some time in 2024 it fell ill and died (just like Dorcas - it must be prophesy!). Probably what happened is that it was unplugged or there was a power outage, and then either nobody could figure out how to (or didn’t want to) turn on the crotch-speaker.
Subsequently, the speaker was removed and various random wires and crappy speakers were shoved into the chest cavity in the vain hope it would start working again. The SD card also had bad sectors and the Pi was starting to boot unreliably. The LCD screen had long since been removed by some fiendish parts pilferer.
Poor little Dorcas needs a refit, so here we are.
Version 2.0 of UrchinWare(tm) has some minor changes:
Full re-write - the old code was horrible (Jeeer!):
- Putting data in Sqlite3 rather than hard-coding everything (wowsers!)
- Splitting modules into separate files (zammo!)
- Stripping out the display parts since there is no display (hurrah!)
- Simpler dependencies (no more Qt or need for a display server - huzzah!)
- New features! (zaaaaap!)
Install your OS on the device where you want to run this project. The Nottinghack Urchin runs on a RPi 3. At various times the base OS has been Raspbian (lite image) and OpenEuler. Some extra packages must be added over a base install (Raspbian package names here):
soxespeakespeak-ngbind9-dnsutilssqlite3pigpiodscanlogd(optional - if you want to be informed of portscans)mosquitto(optional - if you want to run a local MQTT server for testing)
Run: sudo systemctl enable pigpiod ; sudo systemctl start pigpiod
Clone project; create a virtual env and install Python dependencies:
# mkdir /opt # git clone https://github.com/mousefad/urchinware-2.git /opt/urchin # cd /opt/urchin # python -m venv .venv # . .venv/bin/activate # pip install --upgrade pip # pip install .
- Set a couple of environment variables so the program can find relevant files:
$ export DORCAS_DATABASE=/opt/urchin/db.sqlite3 $ export DORCAS_AUDIO_DIRS=/opt/urchin/audio
- Generate a config database from the sample,
dorcas/sample/db.xml(this file is a GNUmeric spreadsheet for easy viewing/editing). This command will generate the file at the path defined byDORCAS_DATABASE.
# python dorcas/database.py load dorcas/sample/db.xml
- Run with
python -m dorcas --config default
The database can store multiple configurations - one per record in the
CONFIGS table. Only one configuration can be active when the program
is running. The configuration to use can be selected using the
--config <id> option when starting the program. If the --config
option is not used, the program will select the record where the ID
field matches the hostname of the machine where the program is running.
A configuration selects a record from the BROKERS table to decide
which MQTT broker to connect to. At time of writing broker certificates
are not supported (since the one at Nottingham hackspace is open /
unencrypted).
Other tables:
VOICES- parameters for theespeaktext-to-speech engine.EFFECTS- post-procesing of speech audio withplay(part of SOX).IGNORES- patterns of MQTT messages to ignore.SPECIAL_DAYS- define holidays and such.GREETINGS- generic and personalized greetings.MUSINGS- responses to general MQTT events and interctions with DonationBot.
The sample config database is provided as a GNUmeric spreadsheet in XML format, which is convenient to read and edit using the GNUmeric Free software application. This can then be converted to an SQLite database withthe following command (from the repo root directory):
# python dorcas/database.py load path/to/spreadsheet.xml
The spreadsheet will be converted into an SQLite database which will be
saved to the path defined by the DORCAS_DATABASE environment
variable.
Editing the spreadsheet and re-generating the SQLite database is a fairly convenient way to work, but you do you - edit that database however you like.
Greetings are triggered when someone enters the front door of the hackspace (i.e. the door is opened from the outside with an RFID card).
One Greeting will be selected and the Action performed. Greetings are
selected from the GREETINGS table in the database as follows:
- Select where
GREETINGS.MEMBER is NULL or GREETINGS.MEMBER == <member_name> - Drop records where
GREETINGS.CONDITIONis notNULLor the condition evaluates toFalse(see Conditions, below). - From the remaining records select one greeting randomly (weighted by
the
WEIGHTvalue). - Perform the ACTION (see Actions, below).
Musings are triggered by sensations. Sensations occur when any MQTT message is seen (with the topic and message from the MQTT message. Some sensations are generated internally (e.g. when Urchin starts up or shuts down, or when Urchin becomes bored).
Every time a sensation is experienced by the Brain, records in the
MUSINGS database table are evaluated as followed:
- Select all records where
MUSINGS.TOPICmatches thetopicof the Sensation. - Drop records where
MUSINGS.CONDITIONis notNULLor the condition evaulates toFalse(see Conditions, below). - From the remaining records select one musing randomly (weighted by
the
WEIGHTvalue). - Perform the ACTION (see Actions, below).
Greetings and Musings are filtered by Conditions. A condition is a Python expression that evaluates to True or False. Conditions are evaulated with a limited execution context with access only to Brain State Variables and the following functions:
random()Call Pythonrandom.random().random_choice(list)Call Pythonrandom.choice(list)random_int(a, b)Call Pythonrandom.randint(a, b).
Actions are small Python programs that are performed as a consequency of a Greeting or Musing. Actions execute in a limited execution context with access only to Brain State Variables and the following functions:
eyes(final, duration=0.5)Fade Urchin’s eyes to intensity levelfinal(value between 0.0 and 1.0), takingdurationnumber of seconds to do so. This operation is non-blocking.log(message)Printmessageto diagnostic output with levellogging.INFO.pause(seconds)Block execution of the action for the specified number of seconds.play(file_id, bg=True, volume=1.0)Play an audio file, found under any of the directories defined in the environment variableDORCAS_AUDIO_DIRS(separated by the:character).volumeis a floating point value between 0.0 and 1.0. Thebgvalue determines if the play operation blocks or if playing of the audio file is performed in the background.publish(topic, message)Publish a message over MQTT with the specified topic and message payload.random()Call Pythonrandom.random().random_choice(list)Call Pythonrandom.choice(list)random_int(a, b)Call Pythonrandom.randint(a, b).say(text, voice="default")cause Urchin to saytextusing voice fromVOICEStable whereID==voice.
Dorcas’ mind holds some state that is visible to most classes, and can be used in Actions and Conditions.
Is cut from Cuckoo Clock-Half hour.wav by lonemonk –
https://freesound.org/s/88725/ License: Attribution 3.0
Tannoy chime 02.wav by kwahmah_02 https://freesound.org/s/245953/
License: Attribution 3.0
- MQTT re-connection
- Studio ceiling vibration sensor rules
- Greetings for people with bookings on tools, e.g. “your booking on the starts in 25 minutes.”