Smart Poi

MQTT port 1883 – access denied!

Well things are going really well with the LED Website Indicator project. I re-wrote the firmware, this time using the amazing Autoconnect library (UI for managing MQTT broker and WiFi) and PubSubClient.

The new D1 mini and shield have arrived at the factory – along with a fancy new 3d print cover, so we uploaded the firmware and reached out to friends to test the WordPress plugin – in order to see some flashing lights. No lights. One friend even had his managed WordPress install locked (he wasn’t allowed to install new plugins, some sort of restricted mode – luckily a call to customer support resolved the issue quickly).

After a lot of troubleshooting I finally worked out the issue (on two different servers so far): the admins have locked down outgoing messages and closed most ports – including the one I’m using in the LED-SITE-INDICATOR WordPress plugin, port 1883. Long story short, we can’t have outgoing MQTT messages on all servers (it works on mine though).

So I had to re-write the PHP code as well, removing the MQTT and replacing with http call to an api – which then does the MQTT stuff, on my own server which is allowed.

Conclusion

Check out the LED Website Indicator project – launching any day now!

I got banned from Ngrok after 10 requests!

Reverse Proxy

So in order to test a new payment provider for a site I was looking around for a quick and easy reverse proxy. I didn’t have to look far as Ngrok is clearly the market leader, with a free tier to boot. They also have a convenient Python library called pyngrok for integration with Flask.

Secure Payment

So the payment provider has an easy system where you generate a form and fill it with details (customer, order details, etc) which once posted redirects to their payment processing page – so your standard “Pay Now” procedure. My error in conception was I ignored the docs and thought that this could be handled through the back end (for “security”) so I sent the form from Flask and returned the “Pay Now” page to the front end – also through Flask.

What went wrong?

In hindsight it seems fairly obvious to me that this is exactly how a bad guy would behave – only changing the html along the way. Ngrok service, which my requests and responses was routing through – from my laptop to the payment provider and back – thought the same. They monitor for exactly this type of behaviour I found out.

What happened?

I was banned! The routing stopped working and an error message appeared instead of my self-hosted site. I did contact support and after explaining myself the free account was actually re-instated, but not before two days had passed.

Reverse proxy using WireGuard

So I learned something about what not to do when processing payments. I wanted to keep learning more (and hopefully get to the point where I can process payments for the service I’m working on) so I needed a reverse proxy to receive messages direct from the payment provider sandbox on my laptop. So I found this site (by ducking the term “alternatives to Ngrok”) here: https://github.com/anderspitman/awesome-tunneling and from there I got to this free, open source service built with WireGuard: https://tunnel.pyjam.as/

Now I can host my own reverse proxy (using DigitalOcean droplet) and get back to learning about payment providers, phew!

Don’t Copy VirtualHost files from https to http

This is really just a note to myself, regarding Apache VirtualHost files (probably applies to Nginx too). I spent a good hour trying to fix something that wasn’t broken today, isn’t that always the way. Turns out I left the part in that says “always load the https config” in which of course wasn’t there for an http only site (yes I’m using letsencrypt but not for this particular temporary setup..)

Also what is up with GoDaddy? I can’t get their Nameserver change thing to work. Apparently (according to the customer representative I chatted to) the initial DNS setup takes 5 (!) days on their side, after registering the domain. Actually first he told me to try it in an incognito window – which I had already tried after googling for a bit. I’m not entirely sure that the info I got was accurate but giving the benefit of the doubt for now, since I did forget and clicked on a few settings changes (and quickly changed them back) so it could be me.

End RAnt

Notes for updating LibreElec to a new version

LibreElec has been my home media center (currently running on a modest Orange Pi PC) for many years now. Every now and then I need to update to the latest version, which involves a fresh SD card and some bit of configuration. The following is just some notes to myself (maybe it will help you also?)
Currently updating my system from LibreElec 10 to 11.

YouTube Setup

This involves setting up the YouTube Data Api and some keys (5 of them!). A bit laborious without copy-paste (todo: is there an easier way?)
Here is a link to a walk-through that helped me (2023)

https://www.firesticktricks.com/youtube-kodi-addon.html

Note: they did omit the step where you have to “publish” the app on google cloud account, it doesn’t work it it’s just set to “testing”.

Other Addons (my favourites)

  • TVO*currently not working, requires an updated version from the repository?
  • TVO Kids
  • Red Bull TV
  • Crackle TV
  • Nasa TV

Additional Repositories

Not everything is available in the Kodi default repo. Installing addons like Netflix and Showmax require an extra step

Example walk-through for Netflix: https://howtomediacenter.com/en/install-netflix-kodi-addon/

Samba and SSH

To do any serious configuration (see below), the media center needs at minimum a static ip set up, and additionally I like to set the firewall and samba file sharing (handy for accessing media files over the network).

Remote Control setup:

My Orange Pi PC comes with an IR receiver, which is pretty easy to configure in LibreElec. I have an old DVD player remote which I use for this. Nowadays I just have to copy the config file over to the new installation and set it with one command (over ssh):

Here is the link to the docs for setting up a new remote: https://wiki.libreelec.tv/configuration/ir-remotes

Docker:

LibreElec is able to run Docker containers in the background which gives it a whole additional functionality. The three containers I always install first are Portainer for managing containers, Pi-Hole for network-wide ad blocking and Transmission torrenting (for downloading large OS images overnight, use with the transmission-remote app in F-Droid store).

Pi-Hole setup instructions (with Portainer): https://homenetworkguy.com/how-to/install-pihole-on-raspberry-pi-with-docker-and-portainer/ – after installing “Docker” addon and installing Portainer via the command line:

docker volume create portainer_data

docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data --restart always portainer/portainer

Set up Portainer by using the browser, go to libreelec network ip eg: 192.168.8.11:9000 – assuming static IP is set up already.

The OrangePi PC is pretty low on specs, so it doesn’t handle any massive background services, but there are Docker containers for loads of useful things like ZoneMinder security, Jellyfin media streaming app, Home Assistant home automation and much more.

Other things:

Change the time to correct timezone.

Set the audio source (mine was set to HDMI out by default) settings -> audio, set to ALSA

Add some other addons like TMDB metadata addon (for local file naming and info).

Set media file locations (on HDD) and scan to add metadata (using addon). This applies to music as well as video. Takes a long time (todo: is there a way to copy the old data across?)

Shout out to ChatGPT for making code documentation easy

Just a quick shout out to ChatGPT for helping me with some drudgery in my job. I think this is the best use for it – basically summarising text.

I do have reservations about the skill of ChatGPT and others when it comes to actual coding, having tried ChatGPT, HuggingChat and Claude, as well as Bard and Bing.

That’s it really. Docstrings for Python, JSDoc for JavaScript, etc. Just type something like “Please add c++ documentation for the following function in a class”. Or just “Add documentation here” works fine. If you are in a hurry you can type “docs” and it will most likely get the idea. You follow this up by a paste of your code of course.

Here is a sample of some cool looking documentation I generated recently for a Python helper class – with help from my new coding buddy, ChatGPT.

Don’t forget, always check the output from ChatGPT – it is often horribly wrong, trust me!

The free ChatGPT course was a lot of fun

About a month ago I completed the free course – direct from OpenAI – called “ChatGPT Prompt Engineering for Developers”

This course uses the OpenAI api and helps you create interactive chatbots with a purpose. I promptly started working on a chatbot to take orders for my entertainment company – Big Top Entertainment.

The instructions I gave to the bot included a price list for services and motivation (“you are a customer service agent, make sure to get payment”) and just for fun I included the option to accept chickens as payment. Here is an example conversation with the bot I coded (in Python):

Welcome to Big Top Entertainment Chat Bot, how can I help you?
Enter text: I need some Balloons pls
Assistant: Hi there! Great to hear that you’re interested in our Balloon Twisting service. How many hours of Balloon Twisting would you like to order?
Enter text: 4 hours
Assistant: Awesome! We can definitely arrange that for you. Just to confirm, you’d like to order 4 hours of Balloon Twisting, correct? Also, when would you like to schedule this service?
Enter text: monday
Assistant: Sure thing! Just to clarify, would you like to schedule the Balloon Twisting service for this coming Monday? And what time would you like the service to start?
Enter text: 2pm
Assistant: Great! So, to confirm, you’d like to schedule 4 hours of Balloon Twisting starting at 2pm this coming Monday. Is that correct?
Enter text: yes
Assistant: Perfect! I have you down for 4 hours of Balloon Twisting starting at 2pm this coming Monday. Is there anything else you’d like to add to your order? Maybe some Face Painting or Stilt Walking?
Enter text: No thanks
Assistant: No problem at all. Just one last thing, could you please provide me with the address where you’d like the Balloon Twisting service to take place?
Enter text: 4 Bigtop Lane
Assistant: Thank you! We have your order for 4 hours of Balloon Twisting at 4 Bigtop Lane on Monday at 2pm. The total cost for this service will be R1600.00. We accept payment in cash or chickens, with each chicken valued at R100. How would you like to proceed with payment?
Enter text: chickens
Please try again in a second (rate limiting)chickens
Enter text: chickens
Assistant: Great! We accept chickens as payment. Please let us know how many chickens you would like to use to pay for the service.
Enter text: chickens
Assistant: I apologize for the confusion. Could you please let me know how many chickens you would like to use to pay for the service?
Enter text: how many does it cost?
Please try again in a second (rate limiting)
Enter text: how many chickens??
Assistant: I apologize for the confusion. The cost of the Balloon Twisting service is R1600.00. Since each chicken is valued at R100, you would need to provide 16 chickens to cover the cost of the service.
Enter text: OK great here you go 16 chickens
Assistant: Thank you for your payment of 16 chickens. We have received your order for 4 hours of Balloon Twisting at 4 Bigtop Lane on Monday at 2pm. We look forward to providing you with our service. If you have any further questions or concerns, please don’t hesitate to contact us. Have a great day!
Enter text: Thank you!
Assistant: You’re welcome! It was a pleasure doing business with you. Have a great day!
Enter text:

Conclusion

Chat bots are fun to code. Clearly I could have expanded on this with a full web interface, handing off to a payment gateway (chicken farm?) etc but it was enough to get the idea.

I don’t think I will be going further with the paid api after my $5 free trial expires though (actually it’s my second one so far – tip: duckduckgo email aliases are great if two factor isn’t enforced). In further testing I managed to make a booking of 4 months straight (7 days per week) for 20 face painters – which we would never do – and in addition the bot refused to send a truck to collect the chickens (“As an AI Language Model, I am unable to do that…”). It did, however, refuse to take bookings of more than 8 hours per day. I didn’t tell it that, but we wouldn’t take anything longer for sure.

I have already attempted to do the same using huggingchat api but they changed something halfway and I gave up on it for now. Next time I am bored I will have another look, since it’s actually open source and self-hostable.

Image Classification for Magic Poi images using Machine Learning

The title says it all. Here are a couple of video’s to demonstrate the process:

Testing the version 5 ML model accuracy:

Testing the image recognition model

Deployed using temporary database:

I added a filter for different categories found by the machine learing model

Todo:

  • New images uploaded are not categorized – because I did the classification at home and just uploaded the database. I still need to get the image recognition to work on the server.
  • Scrolling is really not great, gets stuck sometimes and also new images loaded aren’t filtered.
  • Re-categorizing support – and support for more than one category per image
  • Remove bad images (or just hide them).
  • Refine the model to do better (“text-img” recognition isn’t great, for example).
  • Add more categories.

The categories are live! Check out http://magicpoi.circusscientist.com (and sign up for the good stuff).

Sign up for updates:

UPDATES:

Sign up for our update alerts:

bin files and Magic Poi

I recently received a question via email which I thought might need a bit of answering – “Hello, may I ask how to convert the image into a bin file? I couldn’t find the source code on the website and look forward to your reply. Thank you very much.” Here is my response:

(tl:dr I didn’t share source yet but there are two ways to do it)

Great question! I haven’t been working on the file access much yet for the new MagicPoi. The hardware and getting the binary files is coming second to having an easy way to manage images – which I am spending most of my time on right now.

The Android app had a bug with creating .bin files which I never managed to fix, so I did update the “Smartpoi Android App” page to link to two PC programs which you can download – see the page here: https://www.circusscientist.com/smart-poi-android-app/ – just scroll to the bottom to see the (Linux Only) versions. These are easy-to-use drag-and-drop apps which will convert the image files to .bin format and also upload wirelessly to any connected poi. The .bin files are stored temporarily in a folder in the program files, I am sure you can find them there once you try it. I didn’t share the source because frankly the code is a terrible mess which even I am embarrassed about #messyprogrammer – I am getting better at this by the way, look forward to some documentation coming soon!

Currently the magicpoi website api is limited to returning 10 image names. You can see this by typing this into the browser url bar:
http://magicpoi.circusscientist.com/api/get-filenames

To download one of the .bin files listed, you can use the filename(xxx.jpg.bin), also in the browser bar – eg:
http://magicpoi.circusscientist.com/api/output/ajzs2w1aczeq.jpg.bin

Incidentally the example PlatformIO sketch linked from the “api” section here https://www.circusscientist.com/magic-poi-api/ does exactly this, getting the list of 10 files and then using the /api/output endpoint to download .bin files – to the D1 Mini in this case – and then displaying them in 72px. I would have to check but I think maybe all .bin files are compressed to 72px.. yes I checked – currently that’s the default, with option to support any size (thank goodness).

All files which are uploaded using the magicpoi.circusscientist.com site are automatically converted to .bin files. The .bin files are simply compressed image files – with one byte representing one pixel in R3G3B2 format (in the case of MagicPoi I think I rotate them 90 degrees also for the line by line scanning).

To get any image .bin file from the MagicPoi site at the moment you can use a quick hack – if it is an image you uploaded yourself you have to “share” it for this to work. Then scroll down to where the original image is visible (on the “profile” page) – not the rotated version! Right click and select “Open image in new tab” or just “copy url” – then go to the new tab and copy the image name. Now use the name with “.bin” added on for the download api:
http://magicpoi.circusscientist.com/api/output/ajzs2w1aczeq.jpg.bin

I’m sorry I haven’t really been working on the poi hardware and that side of the project. Like I said, I’m focusing right now on front end usability for the web interface. Soon there will be categories for the images, for example, and sorting.

Once the interface is working I will return to hardware and firmware – and also documentation and new features as well as proper api accessibility.

I hope my response answered your question. Everything is a work in progress, but there is progress.

Regards

Tom