updates raspis to new os based on bookworm

This commit is contained in:
Martin Bauer 2024-02-19 08:10:58 +01:00
parent 7776095180
commit 7501ef18a4
25 changed files with 359 additions and 74 deletions

5
.gitignore vendored
View File

@ -1,4 +1,7 @@
ve_*
/server/scripts/docker-images/tagspace/tagspaces
/server/scripts/docker-images/tagspace/*.zip
*.img
*.img
/music
__pycache__
/roles/pi-squeezeserver/backup

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"python.linting.pylintEnabled": false,
"python.linting.enabled": true,
"python.linting.flake8Enabled": true
}

View File

@ -1,21 +1,14 @@
---
- hosts: bedroompi, kitchenpi
roles:
- pi-dhtsensor
- hosts: esszimmerradio
roles:
- pi-standard-setup
- pi-squeezelite-custom
- pi-shairport
- pi-lirc
- pi-sispmctl
#- hosts: esszimmerradio
# roles:
# - pi-standard-setup
# - pi-squeezelite-custom
# - pi-shairport
# - pi-lirc
# - pi-sispmctl
#
- hosts: musikserverwohnzimmeroben
roles:
- pi-standard-setup
@ -26,17 +19,27 @@
- pi-dhtsensor
- pi-squeezeserver
- hosts: bedroompi, kitchenpi
roles:
- pi-standard-setup
- pi-squeezelite-custom
- pi-shairport
- pi-lirc
- pi-dhtsensor
- hosts: octopi
roles:
- pi-dhtsensor
#- hosts: kitchenpi
# roles:
# - pi-standard-setup
# - pi-hifiberry-amp
# - pi-squeezelite-custom
# - pi-shairport
# - pi-lirc
# - pi-dhtsensor
#- hosts: bedroompi
# roles:
# - pi-standard-setup
# - pi-squeezelite-custom
# - pi-shairport
# - pi-lirc
# - pi-dhtsensor
#- hosts: octopi
# roles:
# - pi-dhtsensor
#- hosts: newrpi

View File

@ -28,9 +28,10 @@ all:
esszimmerradio: # oben, eltern
squeezelite_name: Esszimmer
shairport_name: _Oben_Esszimmer
alsa_card_name: Device
#alsa_card_name: Device
squeezeserver: 192.168.178.100
configure_wifi: true
alsa_card_name: 1
musikserverwohnzimmeroben: # oben, eltern
squeezelite_name: Wohnzimmer
shairport_name: _Oben_Wohnzimmer
@ -57,6 +58,6 @@ all:
squeezeserver: 192.168.178.80
router_ip: 192.168.178.1
home_assistant_url: https://ha.bauer.tech
home_assistant_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxNjkxMWIzZmQ4ZWU0NDI0OTg0MjA0ZDllMDhkNGRlMCIsImlhdCI6MTU3ODE3MDU5MSwiZXhwIjoxODkzNTMwNTkxfQ.i7CdXEZy9DV9KPHAl-msK0rOfIUlPYo4zwwJ4UGhXuc
home_assistant_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkM2QxYjAwYjkxZjY0MWVhYjA4YmZhMDYwYTg3YjRhNyIsImlhdCI6MTcwNDI3MDU5MSwiZXhwIjoyMDE5NjMwNTkxfQ.dzvejgEQd9hf-Yftzd7NkR5pv76GaLFczeOy-a2pa1o
configure_wifi: false
wifi_ssid: BauerWLAN

View File

@ -0,0 +1,23 @@
import asyncio
from bleak import BleakScanner
async def main():
stop_event = asyncio.Event()
# TODO: add something that calls stop_event.set()
def callback(device, advertising_data):
print("device", device.address, "advertising_data", advertising_data)
# TODO: do something with incoming data
pass
async with BleakScanner(callback, scanning_mode="active") as scanner:
# Important! Wait for an event to trigger stop, otherwise scanner
# will stop immediately.
await stop_event.wait()
# scanner stops when block exits
...
asyncio.run(main())

View File

@ -0,0 +1,38 @@
import asyncio
import logging
from bleak import BleakClient, BleakScanner
from bleak.assigned_numbers import AdvertisementDataType
from bleak.backends.bluezdbus.advertisement_monitor import OrPattern
from bleak.backends.bluezdbus.scanner import BlueZScannerArgs
async def scan():
args = BlueZScannerArgs(
or_patterns=[OrPattern(0, AdvertisementDataType.MANUFACTURER_SPECIFIC_DATA, b"\x10\x05")]
)
async with BleakScanner(bluez=args, scanning_mode="passive") as scanner:
async for _, advertisement_data in scanner.advertisement_data():
mfr_data = advertisement_data.manufacturer_data
if mfr_data.get(0x02e1):
logging.info("scan(): found correct device: %s", mfr_data)
else:
logging.info("scan(): this should never happen: %s", mfr_data)
async def connect():
device1 = await BleakScanner.find_device_by_address("01:B6:EC:10:CB:8F")
async with BleakClient(device1):
logging.info("connect(): connected to device")
await asyncio.sleep(60)
async def main():
logging.info("main(): starting scan")
asyncio.create_task(scan())
await asyncio.sleep(30)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)-15s %(name)-8s %(levelname)s: %(message)s",
)
asyncio.run(main())

View File

@ -0,0 +1,92 @@
import asyncio
from bleak import BleakScanner
from bleak.assigned_numbers import AdvertisementDataType
from bleak.backends.bluezdbus.advertisement_monitor import OrPattern
from bleak.backends.bluezdbus.scanner import BlueZScannerArgs
from Crypto.Cipher import AES
from typing import Dict
irks = {
"aa67542b82c0e05d65c27fb7e313aba5": "martins_apple_watch",
"840e3892644c1ebd1594a9069c14ce0d" : "martins_iphone",
}
def resolve_rpa(rpa: bytes, irk: bytes) -> bool:
"""Compares the random address rpa to an irk (secret key) and return True if it matches"""
assert len(rpa) == 6
assert len(irk) == 16
key = irk
plain_text = b'\x00' * 16
plain_text = bytearray(plain_text)
plain_text[15] = rpa[3]
plain_text[14] = rpa[4]
plain_text[13] = rpa[5]
plain_text = bytes(plain_text)
cipher = AES.new(key, AES.MODE_ECB)
cipher_text = cipher.encrypt(plain_text)
return cipher_text[15] == rpa[0] and cipher_text[14] == rpa[1] and cipher_text[13] == rpa[2]
def addr_to_bytes(addr:str) -> bytes:
"""Converts a bluetooth mac address string with semicolons to bytes"""
str_without_colons = addr.replace(":", "")
bytearr = bytearray.fromhex(str_without_colons)
bytearr.reverse()
return bytes(bytearr)
def decode_address(addr: str, irks: Dict[str, str]):
"""
addr is a bluetooth address as a string e.g. 4d:24:12:12:34:10
irks is dict with irk as a hex string, mapping to device name
"""
for irk, name in irks.items():
if resolve_rpa(addr_to_bytes(addr), bytes.fromhex(irk)):
return name
return None
def estimate_distance(rssi, tx_power, pl0=54):
"""
RSSI in dBm
txPower is a transmitter parameter that calculated according to its physic layer and antenna in dBm
Return value in meter
You should calculate "PL0" in calibration stage:
PL0 = txPower - RSSI; // When distance is distance0 (distance0 = 1m or more)
SO, RSSI will be calculated by below formula:
RSSI = txPower - PL0 - 10 * n * log(distance/distance0) - G(t)
G(t) ~= 0 //This parameter is the main challenge in achiving to more accuracy.
n = 2 (Path Loss Exponent, in the free space is 2)
distance0 = 1 (m)
distance = 10 ^ ((txPower - RSSI - PL0 ) / (10 * n))
Read more details:
https://en.wikipedia.org/wiki/Log-distance_path_loss_model
"""
n = 2.7
return 10**(( tx_power - rssi - pl0) / (10 * n))
def callback(device, advertising_data):
print(device.address)
decoded = decode_address(device.address, irks)
if decoded:
print(f"{decoded} @ {advertising_data.rssi} distance {estimate_distance(advertising_data.rssi, advertising_data.tx_power)}")
async def main():
# Scan for
args = BlueZScannerArgs(
or_patterns=[OrPattern(0, AdvertisementDataType.MANUFACTURER_SPECIFIC_DATA, b"\x10\x05")]
)
stop_event = asyncio.Event()
#async with BleakScanner(bluez=args, scanning_mode="passive") as scanner:
async with BleakScanner(callback) as scanner:
await stop_event.wait()
asyncio.run(main())

View File

@ -0,0 +1,10 @@
import asyncio
from bleak import BleakScanner
async def main():
devices = await BleakScanner.discover()
while True:
for d in devices:
print(d)
asyncio.run(main())

View File

@ -0,0 +1,58 @@
"""Scan for iBeacons.
Copyright (c) 2022 Koen Vervloesem
SPDX-License-Identifier: MIT
"""
import asyncio
from uuid import UUID
from construct import Array, Byte, Const, Int8sl, Int16ub, Struct
from construct.core import ConstError
from bleak import BleakScanner
from bleak.backends.device import BLEDevice
from bleak.backends.scanner import AdvertisementData
ibeacon_format = Struct(
"type_length" / Const(b"\x02\x15"),
"uuid" / Array(16, Byte),
"major" / Int16ub,
"minor" / Int16ub,
"power" / Int8sl,
)
def device_found(
device: BLEDevice, advertisement_data: AdvertisementData
):
"""Decode iBeacon."""
try:
apple_data = advertisement_data.manufacturer_data[0x004C]
print("apple data", apple_data)
ibeacon = ibeacon_format.parse(apple_data)
uuid = UUID(bytes=bytes(ibeacon.uuid))
print(f"UUID : {uuid}")
print(f"Major : {ibeacon.major}")
print(f"Minor : {ibeacon.minor}")
print(f"TX power : {ibeacon.power} dBm")
print(f"RSSI : {device.rssi} dBm")
print(47 * "-")
except KeyError:
# Apple company ID (0x004c) not found
pass
except ConstError:
# No iBeacon (type 0x02 and length 0x15)
pass
async def main():
"""Scan for devices."""
scanner = BleakScanner()
scanner.register_detection_callback(device_found)
while True:
await scanner.start()
await asyncio.sleep(1.0)
await scanner.stop()
asyncio.run(main())

View File

@ -0,0 +1,3 @@
devices:
martins_iphone: 840e3892644c1ebd1594a9069c14ce0d
martins_apple_watch: aa67542b82c0e05d65c27fb7e313aba5

View File

@ -0,0 +1,8 @@
- name: Apt install bluez and firmware
apt:
name:
- bluez
- bluez-firmware
- firmware-realtek
- firmware-realtek-rtl8723cs-bt

View File

@ -0,0 +1,36 @@
---
- name: Install packages
apt:
name:
- bat
- fish
- fzf
- fd-find
- ripgrep
- lsd
- zoxide
- name: Check if oh-my-fish is installed
stat:
path: '/etc/omf.installed'
register: omf
- name: Download omf installer
get_url:
url: https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install
- name: Execute omf installer
shell: /usr/bin/fish /tmp/install --noninteractive
- name: Execute omf installer
shell: /usr/bin/fish -c omf install
- name: Remove the omf installer
file:
path: /tmp/install
state: absent
- name: Mark oh-my-fish installed with /etc/omf.installed
file:
path: /etc/omf.installed
state: touch

View File

@ -1,10 +1,10 @@
[Unit]
Description=DHT22 Temperature Humidity Sensing
After=multi-user.target
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /usr/bin/dht22_sensing
ExecStart=/usr/bin/dht22_sensing
[Install]
WantedBy=multi-user.target

View File

@ -10,16 +10,18 @@
name: adafruit-circuitpython-dht
executable: pip3
state: absent
extra_args: "--break-system-packages"
- name: pip install adafruit-dht
pip:
name: adafruit-dht
executable: pip3
extra_args: "--break-system-packages"
- name: Install script config
template: src=dht22_sensing.json dest=/etc/dht22_sensing.json
- name: Install script
copy: src=dht22_sensing.py dest=/usr/bin/dht22_sensing owner=root mode=u+rwx
- name: Install systemd service file
copy: src=dht22_sensing.service dest=/lib/systemd/system/
copy: src=dht22_sensing.service dest=/etc/systemd/system/
- name: Add script to autostart and start now
systemd: name=dht22_sensing state=restarted enabled=yes daemon_reload=yes
- name: Add to sysdweb

View File

@ -7,7 +7,7 @@
notify: reboot
- name: Activate Hifiberry
lineinfile:
path: /boot/config.txt
path: /boot/firmware/config.txt
regexp: "^#?dtoverlay=hifiberry-amp"
line: "dtoverlay={{hifiberry_overlay}}"
notify: reboot

View File

@ -1,43 +1,16 @@
---
# Lirc needs a custom build on Raspian Buster, more details here:
# https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=235256
# https://gist.github.com/billpatrianakos/cb72e984d4730043fe79cbe5fc8f7941
- name: Create lirc config dir
file: path=/etc/lirc state=directory
- name: Install lirc
apt:
name: lirc
- name: Install config file lirc_options.conf
copy: src=lirc_options.conf dest=/etc/lirc/lirc_options.conf
- name: Install config file lircd.conf
copy: src=lircd.conf dest=/etc/lirc/lircd.conf
- name: Install remote file
copy: src=hauppauge.conf dest=/etc/lirc/hauppauge.conf
- name: create temporary directory
tempfile:
state: directory
suffix: temp
register: tempdir
- name: Copy over lirc customly compiled lirc packages
copy:
src: debs/
dest: "{{ tempdir.path }}"
when: tempdir.path is defined
- name: Install custom lirc package 1
apt:
force: True
deb: "{{ tempdir.path }}/liblirc0_0.10.1-5.2_armhf.deb"
when: tempdir.path is defined
- name: Install custom lirc package 2
apt:
force: True
deb: "{{ tempdir.path }}/liblircclient0_0.10.1-5.2_armhf.deb"
when: tempdir.path is defined
- name: Install custom lirc package 3
apt:
force: True
deb: "{{ tempdir.path }}/lirc_0.10.1-5.2_armhf.deb"
when: tempdir.path is defined
- name: Activate overlay in boot config
lineinfile:
path: /boot/config.txt
path: /boot/firmware/config.txt
regexp: "^#?dtoverlay=gpio-ir"
line: "dtoverlay=gpio-ir,gpio_pin=17"
register: boot_overlay

View File

@ -1,3 +1,25 @@
Repository: https://github.com/ralph-irving/squeezelite.git
Version: c89faf3280c5dca3f04906a4ff7796a0043e99f0
Packages to build:
- libmad0
- libmpg123-0
- libflac8
- libvorbisfile3
- libfaad2
# for building libssl-dev, libasound2-dev, libflac-dev, libvorbis-dev, libsoxr-dev, libfaad-dev, libmad0-dev, libmpg123-dev
Adapted makefile.rpi
#OPTS = -DRESAMPLE -DDSD -DUSE_SSL -DLINKALL -I./include -I./include/opus -I./include/alac -I/usr/local/include -s -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s
Old
---
Repository: https://github.com/ralph-irving/squeezelite.git
Version: 779fe9035a2dfcaeeb5335497a012d5e7241a409
@ -22,3 +44,4 @@ apt-get install libasound2 libasound2-dev libflac-dev libmad0-dev libfaad-dev li
Then just build with
make -f mymakefile (on a raspi)

Binary file not shown.

View File

@ -6,9 +6,10 @@
name:
- libmad0
- libmpg123-0
- libflac8
- libflac12
- libvorbisfile3
- libfaad2
# for building libssl-dev, libasound2-dev, libflac-dev, libvorbis-dev, libsoxr-dev, libfaad-dev, libmad0-dev, libmpg123-dev
state: present
cache_valid_time: 7200
- name: Remove old config file if present
@ -24,3 +25,7 @@
name: pi-sysdweb
vars:
sysdweb_name: squeezelite
# build with adapted Makefile.rpi:
#OPTS = -DRESAMPLE -DDSD -DUSE_SSL -DLINKALL -I./include -I./include/opus -I./include/alac -I/usr/local/include -s -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s

View File

@ -1 +1,2 @@
http://downloads.slimdevices.com/LogitechMediaServer_v7.9.2/logitechmediaserver_7.9.2_arm.deb
#http://downloads.slimdevices.com/LogitechMediaServer_v7.9.2/logitechmediaserver_7.9.2_arm.deb
https://downloads.slimdevices.com/LogitechMediaServer_v8.4.0/logitechmediaserver_8.4.0_arm.deb

View File

@ -15,9 +15,9 @@
cache_valid_time: 7200
state: present
- name: copy squeezeserver package
copy: src=logitechmediaserver_7.9.2_arm.deb dest=/tmp
copy: src=logitechmediaserver_8.4.0_arm.deb dest=/tmp
- name: install squeezeserver package
apt: deb=/tmp/logitechmediaserver_7.9.2_arm.deb
apt: deb=/tmp/logitechmediaserver_8.4.0_arm.deb
- name: Enable sysdweb autostart
systemd: name=logitechmediaserver state=started enabled=yes
- name: Add to sysdweb

View File

@ -9,6 +9,7 @@
pip:
name: sysdweb
executable: pip3
extra_args: "--break-system-packages"
- name: sysdweb user
user:
name: sysdweb
@ -33,6 +34,6 @@
title = {{sysdweb_name}}
unit = {{sysdweb_name}}.service
- name: Install systemd service file
copy: src=sysdweb-system.service dest=/lib/systemd/system/
copy: src=sysdweb-system.service dest=/etc/systemd/system/
- name: Enable sysdweb autostart
systemd: name=sysdweb-system state=restarted enabled=yes daemon_reload=yes

View File

@ -3,8 +3,9 @@
set -e # exit on error
TARGET_FOLDER="./rpi_image"
IMG_FILE_BASENAME="2021-10-30-raspios-bullseye-armhf-lite"
DOWNLOAD_URL="https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-11-08/${IMG_FILE_BASENAME}.zip"
IMG_FILE_BASENAME="2023-12-11-raspios-bookworm-armhf-lite"
#DOWNLOAD_URL="https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-11-08/${IMG_FILE_BASENAME}.zip"
DOWNLOAD_URL="https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2023-12-11/${IMG_FILE_BASENAME}.img.xz"
echo "This script downloads raspian lite, and modifies the image to enable SSH and set hostname"
@ -28,11 +29,10 @@ wget ${DOWNLOAD_URL}
wget ${DOWNLOAD_URL}.sha256
echo "Checksum verification"
sha256sum -c ${IMG_FILE_BASENAME}.zip.sha256
sha256sum -c ${IMG_FILE_BASENAME}.img.xz.sha256
echo "Unpack image"
unzip ${IMG_FILE_BASENAME}.zip
rm ${IMG_FILE_BASENAME}.zip
unxz ${IMG_FILE_BASENAME}.img.xz
echo "Mounting image"
@ -81,7 +81,7 @@ losetup -d /dev/loop42
rmdir mounted_image/boot
rmdir mounted_image/system
rmdir mounted_image
rm ${IMG_FILE_BASENAME}.zip.sha256
rm ${IMG_FILE_BASENAME}.img.xz.sha256
chmod a+rw ${IMG_FILE_BASENAME}.img .
echo ""