Reinstalls of RPi's

I run multiple RPi's, a 3B and a ZeroW. They are both quite old now and haven't been upgraded to the latest OS. I've had the 3B since mid 2017 and I haven't installed a new Raspbian since I got it...
I've blown the dust off the Pi Zero W and reinstalled the latest version of debian using the Imager https://www.raspberrypi.com/software/
This was so simple and much easier than years before with the old Rasbian OS.
I installed the OS Lite as ill be running headless.
I have a few things connected to the GPIO:
- SainSmart 2-Channel 5V Relay Module (Newer versions are available now...)
- Bosch bme280 module (Digital Temperature/Humidity/Barometric Pressure)
Installation
After updating the distro with sudo apt update, apt full-upgrade.
- GaragePi - https://github.com/Responseless/GaragePi (Custom version of relay trigger for the sliding front gate)
- bme280 MQTT script (logs Temp/Humidity/Pressure to HA)
- bluepy Broodminder bluetooth MQTT script (logs Temp/Weights/Other to HA)
Prerequisites
Were using python3 so we usually would install pip3 and any other python modules your scripts use. On this version of debian on the PiZero W we dont use pip so we can install modules from apt or pip3, depending on the environment.
RPIZeroW >
sudo apt install i2c-tools
sudo apt install python3-smbus
sudo apt install python3-bme280
RPi3B >
sudo pip3 install smbus2
sudo pip3 install RPi.bme280
We're using the I2C so this can be enabled in raspi-config. Interface Options > I2C > enable.
sudo raspi-config
edit the boot config to include the line below:
sudo nano /boot/firmware/config.txt
dtoverlay=w1-gpio
-
sudo nano /etc/modules
w1-gpio
w1-therm
reboot the pi zero
sudo reboot now
Wait a minute for it to restart and connect with SSH again.
get_bme280.py - Pulls current values from the bme280 module temp,humidity, pressure.
#!/usr/bin/python3
import smbus2
import bme280
# bme280 settings
bme280_port = 1
bme280_address = 0x76
bme280_bus = smbus2.SMBus(bme280_port)
calibration_params = bme280.load_calibration_params(bme280_bus, bme280_address)
# the sample method will take a single reading and return a
# compensated_reading object
bme280_data = bme280.sample(bme280_bus, bme280_address, calibration_params)
# the compensated_reading class has the following attributes
print(bme280_data.id)
print(bme280_data.timestamp)
print(bme280_data.temperature)
print(bme280_data.pressure)
print(bme280_data.humidity)
# there is a handy string representation too
print(bme280_data)
create the file with these contents above. Output will show below.
chmod +x get_bme280.py
python3 get_bme280.py
user@pizeroW:~/bme280 $ python3 get_bme280.py
68a1955d-d268-42a4-9795-be981c2071a7
2024-05-09 11:47:50.917301+00:00
24.910461120144465
1013.6039477597245
39.39722134492959
compensated_reading(id=68a1955d-d268-42a4-9795-be981c2071a7, timestamp=2024-05-09 11:47:50.917301UTC, temp=24.910 °C, pressure=1013.60 hPa, humidity=39.40 % rH)
BM_Scan.py
This was a little trickier of an upgrade with the new debian version the bluepy library didnt exist as an apt package (python3-bluepy).
sudo pip install python-pip
sudo pip install bluepy --break-system-packages
We then need to work around this by installing pip and forcing it in. This worked fine and everything installed correctly.
BM_Scan.py – Scans using bluetooth for Broodminder devices and decodes the data.
#!/usr/bin/python3
from bluepy.btle import Scanner, DefaultDelegate
import json
def byte(str, byteNum):
# https://stackoverflow.com/questions/5649407/hexadecimal-string-to-byte-array-in-python
# Trapping for 'str' passed as 'None'
if (str == None):
return ''
return str[byteNum * 2] + str[byteNum * 2 + 1]
def checkBM(data):
check = False
byteCheck = 0
BMIFLLC = str("8d02")
# print (byte(data,byteCheck))
if (BMIFLLC == byte(data, byteCheck) + byte(data, byteCheck + 1)):
print(" Found BroodMinder device")
check = True
return check
def extractData(deviceId, data):
offset = 8 # There are 8 bits less than described in BroodMinder documentation
lbtokg = 0.45359237 # lb to kg
byteNumAdvdeviceModelIFllc_1 = 10 - offset
byteNumAdvDeviceVersionMinor_1 = 11 - offset
byteNumAdvDeviceVersionMajor_1 = 12 - offset
byteNumAdvBattery_1V2 = 14 - offset
byteNumAdvElapsed_2 = 15 - offset # This is the sample number from the device.
byteNumAdvElapsed_2b = 16 - offset
byteNumAdvTemperature_2 = 17 - offset
byteNumAdvTemperature_2b = 18 - offset
byteNumAdvWeightL1 = 20 - offset
byteNumAdvWeightL2 = 21 - offset
byteNumAdvWeightR1 = 22 - offset
byteNumAdvWeightR2 = 23 - offset
byteNumAdvHumidity = 24 - offset
byteNumAdvWeightL2SM_Time0 = 25 - offset
byteNumAdvWeightL2SM_Time1 = 26 - offset
byteNumAdvWeightR2SM_Time2 = 27 - offset
byteNumAdvWeightR2SM_Time3 = 28 - offset
byteNumAdvRealtimeTotalWeight_SwarmState = 29 - offset
byteNumAdvRealtimeTotalWeight = 30 - offset
# BM Models (as of early 2024)
# T (41, 47) # TH (42, 56)
# W (43, 57) # W3/W4 (49)
# SubHub (52) # Hub (54)
# DIY (58) # BeeDar (63)
# Current sample number from the device.
sampleNumber = int(byte(data, byteNumAdvElapsed_2b), 16) + int(byte(data, byteNumAdvElapsed_2), 16)
# Model
modelNumber = int(byte(data, byteNumAdvdeviceModelIFllc_1), 16)
# Version
versionNumber = str(int(byte(data, byteNumAdvDeviceVersionMajor_1), 16)) + "." + str(int(byte(data, byteNumAdvDeviceVersionMinor_1), 16))
print(" Model Number = {}, Version = {}, Sample = {}".format(modelNumber, versionNumber, sampleNumber))
#defaults for non weigth devices
realTimeWeight_lb = 0
realTimeWeight_kg = 0
# if modelNumber == 41 or modelNumber == 42 or modelNumber == 43:
# continue
if modelNumber == 49 or modelNumber == 57 or modelNumber == 58:
weightR = (int(byte(data, byteNumAdvWeightL2), 16) * 256 + int(byte(data, byteNumAdvWeightL1), 16)) - 32767
weightScaledR_lb = float(weightR / 100)
weightScaledR_kg = weightScaledR_lb * lbtokg
weightL = (int(byte(data, byteNumAdvWeightR2), 16) * 256 + int(byte(data, byteNumAdvWeightR1), 16)) - 32767
weightScaledL_lb = float(weightL / 100)
weightScaledL_kg = weightScaledL_lb * lbtokg
weightR2 = (int(byte(data, byteNumAdvWeightL2SM_Time1), 16) * 256 + int(byte(data, byteNumAdvWeightL2SM_Time0), 16)) - 32767
weightScaledR2_lb = float(weightR2 / 100)
weightScaledR2_kg = weightScaledR2_lb * lbtokg
weightL2 = (int(byte(data, byteNumAdvWeightR2SM_Time3), 16) * 256 + int(byte(data, byteNumAdvWeightR2SM_Time2), 16)) - 32767
weightScaledL2_lb = float(weightL2 / 100)
weightScaledL2_kg = weightScaledL2_lb * lbtokg
# print(" Scale R1 kg = {}".format(weightScaledR_kg))
# print(" Scale R2 kg = {}".format(weightScaledR2_kg))
# print(" Scale L1 kg = {}".format(weightScaledL_kg))
# print(" Scale L2 kg = {}".format(weightScaledL2_kg))
# print(" Scaled Total kg = {}".format(weightScaledR_kg+weightScaledR2_kg+weightScaledL_kg+weightScaledL2_kg))
realTimeWeight_lb = ((int(byte(data, byteNumAdvRealtimeTotalWeight), 16) * 256 + int(byte(data, byteNumAdvRealtimeTotalWeight_SwarmState), 16) - 32767 ) / 100)
realTimeWeight_kg = round(realTimeWeight_lb * lbtokg, 2)
realTimeWeight_lb = round(realTimeWeight_lb, 2)
# print(" realTimeWeight kg = {}".format(realTimeWeight_kg))
batteryPercent = int(byte(data, byteNumAdvBattery_1V2), 16)
# Temps
temperatureDegreesC = int(byte(data, byteNumAdvTemperature_2b) + byte(data, byteNumAdvTemperature_2), 16)
temperatureDegreesC = (float(temperatureDegreesC) - 5000) / 100
temperatureDegreesF = round((temperatureDegreesC * 9 / 5) + 32, 2)
temperatureDegreesC = round(temperatureDegreesC, 2)
# Humidity (0 for 41/47/49/52)
if modelNumber == 41 or modelNumber == 47 or modelNumber == 49 or modelNumber == 52:
humidityPercent = 0
else:
humidityPercent = int(byte(data, byteNumAdvHumidity))
#print(" Weight = {} kg {} lb, TemperatureC = {} C {} F, Humidity = {} %, Battery = {} %".format(realTimeWeight_kg, realTimeWeight_lb, temperatureDegreesC, temperatureDegreesF, humidityPercent, batteryPercent))
data = {"sampleNumber": sampleNumber,
"modelNumber": modelNumber,
"versionNumber": versionNumber,
"sampleNumber": sampleNumber,
"batteryPercent": batteryPercent,
"realTimeWeight_lb": realTimeWeight_lb,
"realTimeWeight_kg": realTimeWeight_kg,
"temperatureDegreesC": temperatureDegreesC,
"temperatureDegreesF": temperatureDegreesF,
"humidityPercent": humidityPercent
}
print (data)
json_data = json.dumps(data)
def processData(pdev):
if (checkBM(pdev.getValueText(255))):
print(" Device {} ({}), RSSI={} dB".format(pdev.addr, pdev.addrType, pdev.rssi))
for (adtype, desc, value) in pdev.getScanData():
print(" %s = %s" % (desc, value))
# Trap for the BroodMinder ID
if (desc == "Complete Local Name"):
extractData(value, pdev.getValueText(255))
# Trap for evertyhing
extractData(value, pdev.getValueText(255))
class ScanDelegate(DefaultDelegate):
def __init__(self):
DefaultDelegate.__init__(self)
def handleDiscovery(self, dev, isNewDev, isNewData):
if isNewDev:
# print(" Discovered device {}".format(dev.addr))
processData(dev)
elif isNewData:
# print(" Received data from {}".format(dev.addr))
processData(dev)
scanner = Scanner().withDelegate(ScanDelegate())
devices = scanner.scan(30.0)
The scripts are on my github with their equivalent MQTT versions (in progress).
GIT Links: TBA
Pi Zero W - SSH Lag Issue
The issue is Wifi power saving mode. This can be disabled by adding the file:
/etc/NetworkManager/conf.d/default-wifi-powersave-on.conf
with contents:
[connection]
wifi.powersave = 2
Details here: https://gist.github.com/jcberthon/ea8cfe278998968ba7c5a95344bc8b55