How to send and receive BlueSky posts with a Raspberry Pi Pico W

by Pelican Press
9 views 28 minutes read

How to send and receive BlueSky posts with a Raspberry Pi Pico W

It seems that alternative social media platforms to X (formerly Twitter) are gaining popularity, with BlueSky now reaching 15 million users. Politics aside, I’ve been tri-wielding X, Mastodon and BlueSky and all have their strengths and weaknesses. 

One of X’s strengths was apps and bots. We could easily use the developer API to build an app that interacted with users, and with the advent of the Raspberry Pi, we were able to use X to interact with the GPIO. A Raspberry Pi with sensors could communicate data to your X followers, your followers could trigger the NeoPixels on your Raspberry Pi Pico W to change color. We can also do this with Mastodon, and that is something that I need to investigate further, but here is where BlueSky comes in.

BlueSky

(Image credit: Tom’s Hardware)

Last week I saw a message about atprototools, an API for BlueSky which enables the same functionality found in X, but using the BlueSky platform. I was skeptical at first but I gave it a try. It worked really well and I have a Python app running in less than an hour. But, I wanted something more useful and for that I needed a Raspberry Pi, so I started to investigate migrating the app to a Raspberry Pi 5, and sure that would work, but then fellow maker and BlueSky user Mike Bell had an idea. Bell’s idea was to see if the atprototools module could be used on a Raspberry Pi Pico W. A couple of hours later, we could read posts from BlueSky on a Pico W. A few more hours, and Bell had managed to post to BlueSky from a Pico W.

That was all I needed to create this how to. We’ll be building a Raspberry Pi Pico W powered device that reads the latest post from our BlueSky account (and only our account) and then checks the temperature using a DHT11 temperature sensor. The temperature is then posted as a message to BlueSky. The Pico W then waits for another message to trigger the process.

Don’t use this to spam or become a nuisance. When testing, use it with a spare account to prevent ruining the experience of your followers. 

Finally, and most importantly, many thanks to Mike Bell for their help and work which made this how to possible.

For this project you will need

  • BlueSky account
  • Raspberry Pi Pico W
  • 1 x Breadboard
  • 1 x LED
  • 1 x 100 Ohm resistor (Brown-Black-Brown-Gold)
  • 1 x DHT11
  • 5 x Male to male jumper wires
  • Thonny installed to your computer

Building the Demo Circuit

(Image credit: Tom’s Hardware)

The demo circuit has two sections. The LED and the DHT11 temperature sensor.

First we shall tackle the LED.

(Image credit: Tom’s Hardware)
Swipe to scroll horizontally
Raspberry Pi Pico GPIO Wire Color LED Connection
GPIO 15 Green Anode (+, long leg)
GND Black Cathode (-, short leg) via 100 Ohm resistor

The LED has only two pins. The Anode (long leg) and the Cathode (short leg). The Anode connects directly to GPIO 15 on the Raspberry Pi Pico W. The Cathode connects to any GND pin on the Pico W, via a 100 Ohm resistor. The resistor will limit the current that the LED consumes, prolonging the life of the LED.

Finally, the DHT11 temperature and humidity sensor. Which has four pins, but only three can be used.

Swipe to scroll horizontally
Raspberry Pi Pico GPIO Wire Color DHT11
3V3 (Physical pin 36) Red Pin 1
GPIO 17 Yellow Pin 2
GND Black Pin 4

Power for the DHT11 comes from the Raspberry Pi Pico’s 3V3 pin which connects to pin 1 on the DHT11. The data connection is pin 2 of the DHT11, and this connects to GPIO 17 on the Pico W. This is how we get the temperature data. Finally pin 4 on the DHT11 is GND, and that can connect to any GND on the Pico.

Check your wiring, and when ready move on to the coding section.

Coding a BlueSky Temperature Bot

These steps are how we need to set up the Raspberry Pi Pico W at the time of writing. This is highly likely to change in a few weeks / months, but I will keep an eye on things, and update accordingly.

1. Follow up to, and including step 6 of this how to, so that your Raspberry Pi Pico W is running MicroPython, and connected to your computer running Thonny.

2. Create a new blank project and copy the code from here, and paste it into the new blank file. This is the code that Mike Bell has modified to run on the Raspberry Pi Pico W.

3. Save the file as atprototools.py to the root of your Raspberry Pi Pico W.

4. Create another blank file and copy the code from here and paste it into the blank file. Save the file as datetime.py to the root of the Raspberry Pi Pico W. We need datetime so that the atprototools module can correctly retrieve and send our BlueSky posts.

5. Open a browser to your Bluesky account, and click on the Settings cog and scroll down to App Passwords.

(Image credit: Tom’s Hardware)

6. Click on Add App Password.

(Image credit: Tom’s Hardware)

7. Name the App password “Python” and click on Create App Password.

(Image credit: Tom’s Hardware)

8. Copy the code to a text file and click Done. You will not see this code on Bluesky again!

(Image credit: Tom’s Hardware)

9. Back to Thonny, create a new file and in the file create four objects, SSID, PASSWORD, BSKY_USERNAME and BSKY_PASSWORD. Inside the quotation marks enter your details. Your Bluesky username should be the last part of your profile URL, so for me “biglesp.bsky.social”. The BSKY_PASSWORD is the app password that we created earlier.

SSID = “YOUR WI-FI ACCESS POINT”
PASSWORD = “YOUR WI-FI PASSWORLD
BSKY_USERNAME= ‘YOUR BLUESKY HANDLE”
BSKY_PASSWORD = “THE APP PASSWORD”

10. Save the file to your Raspberry Pi Pico as secrets.py.

11. Create a new file for the project code.

12. Import modules of pre-written code for Wi-Fi access (network), BlueSky (atprototools), our Wi-Fi and BlueSky credentials (secrets), Network Time Protocol (ntp), pausing the code (sleep) and controlling the GPIO (machine).

import network
from atprototools import Session
from secrets import SSID, PASSWORD, BSKY_USERNAME, BSKY_PASSWORD
import ntptime
from time import sleep
from machine import Pin

13. Create an object, led, which will tell the code which GPIO pin our LED is connected to. Then use it to turn the LED off.

led = Pin(15, Pin.OUT)
led.off()

14. Using an object called wlan, connect the Raspberry Pi Pico W to your Wi-Fi. This will set the Wi-Fi to active, then try to connect to your AP, if it fails (False) it will keep trying every second.

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)
while wlan.isconnected() is False:
   print('Waiting for connection...')
   sleep(1)

15. Using ntp, set the current time and date. We need to do this so that our Pico W and BlueSky have a common time reference, otherwise the code will crash.

ntptime.settime()

16. Create an object, session, and use it to connect to BlueSky.

session = Session(BSKY_USERNAME, BSKY_PASSWORD)

17. Create an exception handler to try and run the code, which starts with a while True (forever) loop.

try:
   while True:

18. Create an object, latest_bloot, and use it to store the returned data from our BlueSky session. Essentially it is a dump of what the Python API can see from BlueSky, formatted into JSON.

       latest_bloot = session.getLatestBloot(BSKY_USERNAME).json()

19. Using an if conditional statement, check the last message from your user account. If it contains the phrase “Temp Check” (exactly) then the condition will be True, and the code below will activate.

       if latest_bloot['feed'][0]['post']['record']['text'] == "Temp Check":

20. Use a for loop to flash the LED three times. This tells us that the Pico W has received the command.

           for i in range(3):
               led.on()
               sleep(0.3)
               led.off()
               sleep(0.3)

21. Measure the temperature using the DHT11, round the returned value to two decimal places, and then convert the temperature to a string for use in a message. Note that the returned temperature is in degrees Celsius.

           sensor.measure()
           temp = round(sensor.temperature(),2)
           temp = str(temp)

22. Create a BlueSky post that identifies the context of the message, and appends the data to the end. In this case the room temperature, followed by the actual temperature in degrees Celsius.

           post = session.postBloot("The room temperature is "+temp+"C")

23. If there is no message from the user, create an else condition to force the Pico W to wait, add a sleep to stop the loop running too fast. Note that BlueSky does have rate limiting, so our constant check for new messages may see the Pico W disconnect. We’d advise checking once per minute at the very most.

       else:
           print("Waiting for message")
       sleep(60)

24. Create an exception to capture any Key Errors. These are errors created when the returned JSON feed contains no data, usually when we hit a rate limit.

except KeyError as e:
   print('I got a KeyError - reason "%s"' % str(e))

25. Save the code as bsky.py to the root of the Raspberry Pi Pico W.

26. Click on the green Run button to start the code. Your Pico W will attempt to connect to your Wi-Fi, and once connected, the script will check the latest message in your feed for “Temp Check”. When that message appears, the code will activate, flashing the LED three times, and then take a temperature reading, which is then posted to BlueSky.

Complete Code Listing for bsky.py

import network
from atprototools import Session
from secrets import SSID, PASSWORD, BSKY_USERNAME, BSKY_PASSWORD
import ntptime
from time import sleep
from machine import Pin
import dht
sensor = dht.DHT11(Pin(17))
led = Pin(15, Pin.OUT)
led.off()
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)
while wlan.isconnected() is False:
   print('Waiting for connection...')
   sleep(1)
ntptime.settime()
session = Session(BSKY_USERNAME, BSKY_PASSWORD)
try:
   while True:
       latest_bloot = session.getLatestBloot(BSKY_USERNAME).json()
       if latest_bloot['feed'][0]['post']['record']['text'] == "Temp Check":
           for i in range(3):
               led.on()
               sleep(0.3)
               led.off()
               sleep(0.3)
           sensor.measure()
           temp = round(sensor.temperature(),2)
           temp = str(temp)
           post = session.postBloot("The room temperature is "+temp+"C")
       else:
           print("Waiting for message")
       sleep(1)
except KeyError as e:
print('I got a KeyError - reason "%s"' % str(e))



Source link

#send #receive #BlueSky #posts #Raspberry #Pico

You may also like