MU|TH|UR v1.5 - PTT and two Telegram bots

Back when we ran High Frontier: The Drake Objective in 2024 I used a Raspberry Pi to turn Telegram messages into the "sad computer voice" prevalent in sci-fi movies.

This was a surprise hit in the game but there were a few problems...

  • One of our players is very hard of hearing - so unable to engage with much pure audio content
  • It's really easy to miss random out of the blue messages from a walkie-talkie unless you're actively engaging with it in the moment. Doubly so if somebody is talking to you in person at the time. We were asked to repeat messages all the time.
  • It used voice activation on the walkie-talkie doing the transmitting which wasn't totally reliable and it would occasionally clip the start of messages despite making a "beep" before talking
All of these were related to me just bashing it together in the fortnight before the event while also working on other stuff.

For High Frontier: The Weyland Factor we wanted to fix these and perhaps also have it transcribing incoming messages from the walkie-talkies for MU|TH|UR v2.0.

I started on the update then quickly decided to drop the transcription and constrain the project to just fixing the acknowledged problems before doing something that could suck a load of time and effort. 

The frequency range of audio transmitted by PMR walkie-talkies is limited and it can be hard for a person paying attention to distinguish speech sometimes so I surmised automated transcription would do more poorly, even the cloud based 'AI' version of it.

My original version had a single Telegram bot that was part of a group chat with a simple command interface. The event GMs could chat in the group normally but anything prefixed with the command "/say" would be turned into speech and sent to the PMR. The bot was just one of Telegram's example bots and Microsoft's Azure speech to text example smushed together, but it worked well. With no WiFi on-site I relied on a 4G dongle I had kicking around that "just worked" in the Raspberry Pi.

Everything looks like a nail

As Telegram worked well for the GM group and I had a load of Android tablets with LTE modems from other events, the obvious way to give the players a text channel to interact with MU|TH|UR through was just another group chat in Telegram.

While I had physical carry cases for the tablets the interface couldn't be skinned to be "diegetic" with the time I had. They just had some Android Tablets and Telegram but this is not an immersion destroying thing and to do anything else would have been a big pile of work. A custom Android app or Progressive Web App is something that's in my wish list for the future but wasn't realistic for this event.

So with two chat groups that created a requirement for two bots if I wanted to "separate control messages from user messages" which is a good design pattern even though this isn't exactly a highly sensitive application.

Two bots, one script

All the main Telegram bot Python examples are for one bot, which is fair enough. I am not a Python programmer and quickly found that the 'blocking but async event driven' default way of writing bots with the common library is inimical to running two bots at once. Well not exactly but you then can't use the 'convenience' methods and have to engage with the Telegram API at a lower level. Several people have asked for a multiple bot example but the library maintainer's response was of the vaguely dismissive "read the docs/now draw the rest of the owl" variety. Likewise lots of other responses kicking around on a search have pseudocode partial examples that just didn't run even when I tried to fill in the blanks.

So, sledgehammer to crack a nut time and I quickly taught myself how to use the multiprocessing library in Python. Wasteful but it's only a Telegram bot talking to webhooks on a system with one job to do. The two bots talk to each other via a multiprocessor Queue: player messages are passed to the GM bot and GM messages intended for distribution are passed to the player bot. Not unexpectedly there seems to be a lot of subtlety about whether certain things are thread safe in Python when using the async.io method the Telegram library uses itself. I think using the multiprocessing library and its own inter-process communication method insulates me from that but like I say I'm no Python programmer, my usual playground is C++ and FreeRTOS.

While I was doing this I added a tiny bit more subtlety to the control. Messages prefixed "/say" would go to the player group chat as well as being broadcast as speech. Messages prefixed "/send" would just go to the group chat. This was a speculative feature but ended up being useful.

Push to talk

There's no standard for connecting things to PMR walkie talkies but they do share a kind of common pattern. I used the same circuit as I did for MU|TH|UR v1 to match impedance/levels and added in a relay that grounds the 'tip' connection when you want to transmit.

From this it was simply a case of triggering a GPIO pin before 'speaking' to latch the relay and then release it afterwards.

The end result meant triggering the PMR was now much more reliable and receiving PMRs received the messages more consistently.

When 3G is no longer enough

With not long to go I had it all working and plugged in the dongle to do a bit of a final test. Which then stubbornly refused to work. I spent far too long trying to troubleshoot this, cursing bitrot and version creep in Raspbian but when it occurred to me to try the dongle in my laptop it didn't work there either.

Despite being listed as "4G" in some specs that show up when you search it turns out the dongle I'd been using for ages was actually some variant of 3G that the big switchoff made non-functional. Well it did come from e-waste, which is where it'll go back to. I've got an otherwise usable phone with the same problem.

This prompted a quick panic order of a Waveshare SIM7600G-H dongle from PiHut. There's a certain clunkiness to it as it's intended for industrial/hobbyist use rather than consumers but that at least means no weird gimped branded up firmware and at least some technical information on their Wiki.

Getting it working was definitely not a consumer job, sending AT commands over a USB serial port and then having to reconfigure Network Manager in Raspbian to not set the DNS servers: another frustrating half day rabbithole but with it configured it connects quickly and reliably. The external antenna probably helps.

As it's also possible to use this via an onboard UART I may see if I can use this from embedded hardware like an ESP32 but that's a project for another time.

Sticking it in a box

The new dongle and external antenna meant there was no way the original enclosure where I repurposed an external mains socket box was going to work any more.

So I settled on using a 9l "Really Useful Box" and 3D printed a mounting plate for it all. There's also a fascia with a status LED, a button to shutdown/restart it and some places to cable-tie the cables in place to stop them getting yanked out of the internals. The box isn't properly waterproof long term but will stand use outdoors for the couple of days at a time that we need it.

All the external leads are hugely long. It's powered from a 12v lead-acid battery which needs tucking away somewhere safe and the PMR used to transmit needs some height to help with coverage and ends up tied to a pole high up.

Sometimes the wrong thing is the right thing

Once I'd reached this point of it working reliably and was thinking about how we'd use it in the game it popped into my head we could use What3Words to send the player group directions.

I'm no fan of this attempt to do corporate capture of something there should be an open standard for (there is one but it is a tad clunky) and the failings of their word choice algorithm for safety critical situations have been explored extensively by people smarter than me. However in this case, smacking the W3W app onto the tablets the players were already carrying and then sending locations into the chat as a clickable link that opened the app was a fair choice and we'd used it a little in the past.

Until the event I didn't even get to test it, and when we started using it the "/send" option where MU|TH|UR didn't read out the words was needed because otherwise it was a tide of unintelligible blah when we forgot.

Much as I have reservations about W3W it worked mostly OK for this, only once sending them in completely the wrong direction which was probably a GM mistake, and I think we'll be using this again next year.

Want to build your own?


I've now backed this all up and once I've had time to write an "installer" of sorts I'll update the previous instructions on GitHub.

Looks like love at first sight to me

Recently we finished up our four-episode LARP series, High Frontier: Gods and Monsters, which has been stuck in my consciousness ever since mid-2019. The pandemic delayed the first episode but we've run one episode a year since 2022 and it felt like I always had something for it on my to-do list.

Despite being set in our variant of the Alien/Prometheus universe we had not so far featured any Xenomorphs in the game and that was about to change.

An obvious way to signal this in advance is to feature the iconic visual of a Facehugger in a huge glass tube. I've been meaning to make one of these for years and had an earlier version that never really worked I junked.

Buying a large enough clear tube for the task was something I looked at over time but anything the right size was simply outside our prop budget. Knowing we really wanted this in the game I decided to bend a sheet of 3mm acrylic. How hard could it be?

Turns out it was quite hard.

I picked up a 1800x900mm 3mm acrylic sheet and used this halved as my basis to scale everything else, allowing me to make two tubes.

Not being an RPF level prop maker all my stuff just needs to look "about right". I always prioritise it being repeatably makeable and able to stand transport and handling by random people in the LARP.

You can bend acrylic with heat and last time I need to do larger pieces for ORAC I put them in an oven, which worked fantastically. Short of asking a local bakery nobody has an oven that's going to take square sheets this large. Which meant progressive use of a hot air gun was about the only option open to me.

Having done the calculation on the size of tube this would make it turned out I had a large cardboard tube close so I clamped the acrylic to this and repeatedly formed the sheets over this in a process that ended up taking a couple of days.

Meanwhile I found some reference photos of the original props and started doing a rough replica in CAD for 3D printing. There's a reason I own a large format bed slinger 3D printer, it's slow unfashionable and fairly low quality but it allows me to print larger items like this.

Some time back I had found a 3D poseable printable model of a Facehugger model and had printed all the parts for a couple as I'd planned to make two tubes. These ended up being really quite difficult to assemble even when following the printing instructions. The joints are super tight and even with careful printing on my newer printer and some sanding of the 'knuckles' they were prone to snapping when forced together. In the end I think I printed enough to make three and managed to get two completed ones.

I'd designed the top/bottom sections that hold the tube with a small groove in that should hold the acrylic into its tube shape and make the whole thing kind of seamless so as I got the first pieces off the printer I started to assemble things. Here I realised my mistake, I could see the tube wasn't perfect but 'almost round' and hoped constraining it into the printed pieces would even things out. Getting frustrated I tried to force it in and snapped a large corner chunk off, acrylic is quite brittle.

So we were down to one tube and I spent yet more hours trying to get that acrylic tube properly round.

The two Facehuggers got a rudimentary paint job. I'm a fan of heavy coats of generic DIY emulsion paint and varnish to cover layer lines on organic shapes and it worked out OK. The second Facehugger would still end up getting used laid out on a table.

The top and bottom sections got proper priming and sanding as they needed to look like metal close up.

When I came to fit the remaining tube, despite spending a long time bending it I still struggled to get it to fit, even with constraining it with straps and now realise I should have put a bevel in at least the inside of the slot it's supposed to fit otherwise it's just too hard to do singlehanded. With the LARP only a week away I didn't have time for a second costly mistake so I just taped the tube outside the top/bottom sections and up the back to cover the now large gap. I know it's not right but in the final analysis the players just saw a cool large prop so it did the job.

People with a decent memory of the original will see the control panel piece in the top section never got modelled and printed. I hit "perfect is the enemy of good" quite quickly once we were close to the event so I simply left it out. Now we're past it and I've got an interesting if huge prop to display in my house I think I'll go back and finish it up. I may even try to remove the tape and fit the acrylic properly, perhaps re-printing the round sections with a larger, tapered groove.

3D printed Data Slate props

For a long while I've been using old Nexus 9 tablets to act as 'cyberdecks' in our Cyberpunk LARP, but I was recently asked to dress them for a 40K themed one this summer.

The old 3D printed cases were getting long in the tooth and were clearly just unpainted poor quality 3D prints. So I started completely from scratch for this, only re-using my CAD model of what I needed to hold the tablet securely and operate the power and volume buttons on the side.

One of the major things I wanted to get away from was the obviously rectangular shape of the tablet screen. It's a common sci-fi trope for screens to be weird shapes and to emulate this I modelled a surround with truncated corners and cutouts for the cameras and speakers.

This looks great so long as the tablet is asleep, but once it wakes up the real shape of the screen is obvious. There's only so much I can do here and while I could have covered some of the usable area Android apps tend to quite rightly assume the whole screen is accessible.

On the old tablet holders I had added some old bag carrying straps, which are very practical but untidy looking so I added a very chonky carrying handle as part of the case.

This makes the whole thing physically large, which has the added advantage of making these hard to hide or just stuff in a bag. It's a not uncommon problem in LARP that acquisitive players will squirrel something away in their bag and it's never seen again unless they want to leverage it somehow. These were to have PDFs on them that were plot-relevant and we wanted that information very clearly available.

Annoyingly there's no open source 'kiosk mode' application for Android that I could find but to make sure the PDFs were visible whenever somebody woke the tablet I used the "Librera FD" viewer and the basic screen pinning functionality in Android to keep it maximised.

When asked to make these I wasn't sure how long the documents would be so I decided to add physical controls for paging through and searching documents. There's a scroll wheel, two buttons to page up and down plus a keyboard for text entry. This re-uses an X-Box 360 chatpad as making your own small keyboard keycaps that don't look terrible is very awkward and fiddly. There's also a piezo sounder to do keyboard/button bleeps.

This section is the part I'm least pleased with: the chatpad is too small and the buttons I ordered were too long to allow me to inset it like I did with the tablet section.

The design is ugly because I was rushing and I will most likely re-do this part before they are used again. I may even go as far as making a custom keyboard using tactile switches that fills more of the area.

These physical controls are driven by ESP32-S2 dev boards acting as USB OTG HID devices. I ran into a bit of a struggle with the code for this. Every time the tablet went to sleep, it would disconnect the USB devices and refuse to reconnect. I think this is related to this reported bug but was in a hurry to get this done so just made the ESP32-S2 restart whenever the tablet went to sleep. There is a little latency on waking it up but not a great deal. I would like to add more functionality to this setup, including my LoRa mesh network messaging stuff, so I need to overcome this problem. The 'cheat' would be to connect the ESP32 over BLE but given I have a direct physical connection to the tablet this sort of offends me and I'd need to swap to an ESP32-S3.

In the end though, this all worked out well, I got four of these made in different colours so they could be told apart and the paint weathering on the main body looks good. I didn't have time to weather the control sections so they just got some scratches but if I'm going to re-do them that's fine. I may also try to make some left handed variants and some without the big handle.

These will definitely be getting a load of use. Put Termux on them and they are almost 'real computers' and while the performance is poor in modern web applications we always curate what we let our players access. I've got a drawer full of Nexus 9s so printing and painting a few more of these over the next few months will get me a nice stash of usable props.



3D printing Lasertag lens units

For over a year I've been faffing with my own Lasertag PCB design but keep dropping the project when something else needs doing.

The PCB design seems OK but with a couple of poor decisions I'd fix were I to order more. The 'beta' software works so I fitted them in two of my own Lasertag weapons and one worked great but the other not so much. I think it's got two current limiting resistors because I didn't realise there was one in the existing lens unit already.

What I don't know was what the real potential of the board was with the component choices I'd made.

Having a board design sort of goes hand in hand with needing lens units to match and I want to do what Phil from UKLTA has done: design a re-usable 3D printed lens unit that can be included in larger things, or printed out to attach directly to conversions. This is especially true if I want to maybe make some 3D printed 40K themed weapons for our upcoming 40K LARP

I ordered some 25mm acrylic lenses a few weeks back and I've had a go at designing an adjustable 3D printed lens unit that uses them but what I really needed was a way to range test away from Lasertag events that didn't involve the Police being called on me. Being based in the UK this is a real concern. So last week I made up a 'gun on a stick' which looks nothing like a weapon apart from the attached sight.

Today I've done some testing at the Hackspace on the field and it's "good enough for The Grange" with no trouble hitting a target across the width field at ~140m.

Unfortunately this isn't really a good test as I arrived later than planned and the photos don't really show how much the light was going. I need to test again on a bright sunny day. Home is just a short walk from Wanstead Flats which is a huge area of common ground so I'll have to make a trip there when the sun is shining.

Good progress though.

Hackspace access control

I'm a trustee at East Essex Hackspace which is currently discussing buying a fibre laser and it's rekindled the desire for 'toolbots' to control access to things. Originally I was looking at this over a year ago but got busy with other things so shelved it and then the need suddenly seemed less urgent.

One of our challenges is that when we opened we used some Wiegand RFID readers for our door entry system and fed the UIDs they gave into our membership database. Later on we found out that these UIDs weren't the same as the UIDs other things reported. I did some fiddling around and realised a simple XOR and byte reshuffle that fixed this so we were back in business until I built something using this and found it wasn't right for some issued cards. 

Then the access control project got shelved.

Having dug out my access control mockup again I armed myself with a pile of cards that I know don't map IDs how I thought and quickly realised if they have a 7-byte UID then the byte order reshuffle is different than for a 4-byte UID. So we're potentially back in business.

For the hardware I've taken a bit of an executive decision on the basis that whoever does the work gets to say how it's done, otherwise endless bikeshedding occurs. The hardware will be based on an Olimex ESP32-EVB which is an ESP32 dev board with Ethernet, onboard relays and a bunch of hardware we probably don't need. They're reliably available and properly certified.

To add the RFID reader I've designed a little 'shield' that plugs into the UEXT connector on the EVB which I'll solder some cheap MRC522 boards to.

It also breaks out some GPIO and has LEDs and somewhere to connect a sounder. I'm not even sure if we'll use a sounder, but I just wanted to get the board ordered.

Work on the software has been ongoing for ages but I've started poking at it again and one of the other Trustees already did a bunch of stuff in our membership database so I'm hoping this project can get done without too much pain.

Each tool will have different ways of limiting its use but my expectation most will already have an interlock or emergency stop that can be connected to one of the onboard relays of the EVB. I'd not expect these devices to control the main power feed to the tool unless it's a very small one.

Hoverboard comms library

I'm back making silly moving things using hoverboard hub motors and re-flashed hoverboard controllers.

For months on end I've been vaguely putting off working on the big 6-wheel platform I started because I needed to write a library for the comms protocol so I wasn't committing the sin of copy & pasting great swathes of code to run the three separate controllers.

Now I've finally sat down and got round to it so the excuses for not progressing the big rover project are evaporating. I only started thinking about this two years ago.

MU|TH|UR setup script

I have now (mostly) documented/automated how to create a text-to-speech bot as recently used at our High Frontier LARP.

Instructions are here.

retroTerm release 0.1.6

At our recent LARP High Frontier: The Drake Objective I used retroTerm my ANSI/VT terminal GUI widgets library to create a prop where the players interacted with an offscreen extra-terrestrial intelligence through a purposefully retro computer interface.

This is the whole reason the library got written in the first place.

Work started on retroTerm in maybe 2019. Then the game it was scheduled to be used in got postponed due to the pandemic and despite the extra time that afforded me I didn't manage to deliver anything usable for the game when it finally happened.

It was a terrible case of overpromise and underdeliver, ie. I delivered nothing usable. The work on the retroTerm library itself was fine but the messaging system it was to provide the user interface for just wasn't stable and we abandoned it at the last minute.

When a short 'midqual' LARP event came up last year I rewrote all the messaging code and produced a version of the thing with a cut-down retroTerm user interface that saw a tiny amount of use. There were still some frustrating problems though: centred on it needing an accurate timestamp for all the messages and me getting caught out by GPS just not working for this. I had not realised the building it would be used in had a metal roof and the dubious signal ended up causing it to end up with spurious date & time values, some in 2080. Which is perhaps a failing of the GPS library I used to process the NMEA sentences but regardless this was not good and caused it to misbehave.

As a result when The Drake Objective was announced I made some new hardware that included a hardware real-time-clock and did a ton of work on making damn sure the setup would have a correct time. It couldn't just connect to WiFi and get it from the Internet as it'd be used in a building in a field with no services and also very dubious 4G signal we weren't sure would be usable.

The new hardware worked around the issues well and the whole prop behaved pretty well during a weekend long game albeit in its still quite cut down form.

Part of putting this thing together saw me make some improvements to retroTerm.

I found and squashed a memory leak[1] and have just improved the way it handles 'list box' widgets so I feel it's in a pretty solid spot. Today I fiddled around testing it on an ESP32 over Classic Bluetooth Serial rather than a wired connection and this worked trivially easily.

This is something I can imagine use cases for so I'm glad I finally tried it out. Often ESP32 projects get built with little captive web portals to configure/control them but this gets 'big' quickly. Being able to run a wireless retroTerm interface for this is something I'm going to try in an upcoming project.

Anyway this was all a big ramble to say retroTerm 0.1.6 is out and seems to be working well.

Next on my list is making that multi-user peer-to-peer messaging system I originally promised back in 2019 happen. Even if we never actually use it I want to have done it and to that end have been writing great swathes of code in preparation already which I've been sticking in some new libraries. When they're more finished I'll share them.

[1] Which only showed up if constantly updating something like a clock widget