All posts by Thomas W-P

Spotipy – Squeezeserver

We have an old squeezeserver but hardly use it. Nostalgic for the music, I set myself the task of programatically making a Spotify playlist of all the tracks. Slow progress but I do progress:

  1. Find the squeezeserer sqllite database and export it using Firefox plugin SQLite manage;. I exported csv and cleaned it up in Excel. I can export that as a csv once I nail the rest of it.
  2. Install Spotipy. Follow all the instructions about making an account with the developer side of Spotify.
  3. Try to get the Spotipy example for playlists working. FAIL (authentication).
  4. Try to get WSL Debian to launch a brower so you can authenticate. FAIL.
  5. Try to get Powershell to launch the same. Success! but later fail.
  6. Try to set environment variables in Powershell. FAIL
  7. Tear hair out.
  8. Realise you can hard code the variables in…

OpenHabian as NAS

In my quest to reduce energy I decided to make openhabian my NAS. I can shut down an old ASUS wifi router I have been lazily using for that purpose with an external disk attached. I pulled the PCIe3 USB stick from the TV that is 1TB and never used (I upgraded to Freesat) and shoved it in the Openhabian.

Got it all set up, then used the teminal program screen to set the copying in motion. ctrl+a , d to leave, screen -r to go back in to it.

I always forget the working settings so here are the pages I used and the final critical lines of text in smb and fstab.

/etc/fstab

UUID=82A2524DA2524637 /mnt/nas ntfs rw 0 0

/etc/samba/smb.conf

[NAS]
  comment=PCIe3 NAS
  path=/mnt/nas
  writeable=yes
  public=no
  create mask=0664
  directory mask=0775
  veto files = /Thumbs.db/.DS_Store/._.DS_Store/.apdisk/._*/
  delete veto files = yes

Spotify API and Squeezebox transfer

Had fun and games getting the API to work with spotipy. All due t orustiness and inexpeerience. I just couldn’t get it to authenticate until I realised how to put my credentials in the script.

This was all part of a project to move our entire library of ripped CDs from the Squeezebox to Spotify. I was able to export the database to excel, clean it up, use the excel to make lines of code, then went through in batches of 100. I figured this would be quicker than hacking away maging it work with the spotify paging system as it was a one off task.

I did put the API authentication details in to a json file though:

{"client_id": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
"client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
"redirect_uri": "https://localhost:8080"
}

The code (no promises it is not changed a bit), but it might help someone.

# Shows a user's playlists

import spotipy
from spotipy.oauth2 import SpotifyOAuth
import json

import sys
import pprint

# Opening JSON file
f = open('authorisation.json')
# returns JSON object as 
# a dictionary
data = json.load(f)

f = open('playlist_track_ids.json')
a_track_ids = json.load(f)

# scope = 'playlist-read-private'
# sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=data['client_id'],
#                                     client_secret=data['client_secret'],
#                                     redirect_uri=data['redirect_uri'],
#                                     scope=scope))

# results = sp.current_user_playlists(limit=50)
# for i, item in enumerate(results['items']):
#     print("%d %s %s" % (i, item['name'],item['id']))

scope = 'playlist-modify-private'
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=data['client_id'],
                                    client_secret=data['client_secret'],
                                    redirect_uri=data['redirect_uri'],
                                    scope=scope))


songsAndArtists = {
#'Afro Angel': 'Will Smith',
'Sandstorm': 'Cast',
'Mis-Shapes': 'Pulp',
'Mansize Rooster': 'Supergrass',
'Sleeping In': 'Menswear',
'Getting Better': 'Shed Seven',
'From a Window': 'Northern Uproar',
'The Riverboat Song': 'Ocean Colour Scene',
'Weak': 'Skunk Anansie',
'Divebomb': 'Number One Cup',
'Time': 'Marion',
'Far': 'Longpigs',
'The Universal': 'Blur',
'Dark Therapy': 'Echobelly',
'For the Dead': 'Gene',
'Ten Storey Love Song': 'The Stone Roses',
'Just': 'Radiohead',
'Lucky You': 'The Lightning Seeds',
'Carnival': 'The Cardigans',
'Anywhere': 'Dubstar',
'Come Together': 'The Smokin\' Mojo Filters',
'Fade Away': 'Oasis and Friends',
'Flying': 'Cast',
'Beautiful Ones': 'Suede',
'Everything Must Go': 'Manic Street Preachers',
'Fighting Fit': 'Gene',
'Twisted (Everyday Hurts)': 'Skunk Anansie',
'Lost Myself': 'Longpigs',
'Disco 2000': 'Pulp',
'Ready or Not': 'The Lightning Seeds',
'You\'ve Got It Bad': 'Ocean Colour Scene',
'C\'mon Kids': 'The Boo Radleys',
'Lava': 'Silver Sun',
'Kandy Pop': 'Bis',
'Teenage Angst': 'Placebo',
'Burden in My Hand': 'Soundgarden',
'Celebrity Hit List': 'Terrorvision',
'Boy Wonder': 'Speedy',
'No One Speaks': 'Geneva',
'Great Things': 'Echobelly',
'Nice Guy Eddie': 'Sleeper',
'Sparkle': 'My Life Story',
'Morning Glory': 'Oasis',
'Milk': 'Garbage featuring Tricky',
'6 Underground': 'Sneaker Pimps',
'If You\'re Thinking of Me': 'Dodgy',
'Chasing Rainbows': 'Shed Seven',
'For You': 'Electronic',
'You\'re Gorgeous': 'Babybird',
'Patio Song': 'Gorky\'s Zygotic Mynci',
'Neighbourhood': 'Space',
'Girls & Boys': 'Blur',
'The Frog Princess': 'The Divine Comedy',
'Whatever': 'Oasis',
'Lazy Lover': 'The Supernaturals',
'Lenny': 'Supergrass',
'If You Don\'t Want Me to Destroy You': 'Super Furry Animals',
'Broken Stones': 'Paul Weller',
'If I Could Talk I\'d Tell You': 'The Lemonheads',
'Street Spirit (Fade Out)': 'Radiohead',
'Not So Manic Now': 'Dubstar',
'You\'ve Got a Lot to Answer For': 'Catatonia',
'One Night Stand': 'The Aloof',


}

songsAndAlbums = {
#'Deep Blue Day': 'Trainspotting',

}

i=0
# Iterating over values
for name, artist in songsAndArtists.items():
    
    results = sp.search(q='track:' + name + ' artist:' + artist, type='track')
    items = results['tracks']['items']
    if len(items) > 0:

        track = items[0]
        try:
            a_track_ids.index(track['id'])
            #print('Found: '+track['name'])
        except:
            # #add to the list
            # sp.playlist_add_items(playlist_id='2CE0LjqBpPFqdv2CnToUIh', items=['spotify:track:'+track['id']+''], position=None)
            # a_track_ids.append(track['id'])
            print('***Added: '+track['name'])


i=0
# Iterating over values
for name, album in songsAndAlbums.items():
    
    results = sp.search(q='track:' + name + ' album:' + album, type='track')
    items = results['tracks']['items']
    if len(items) > 0:

        track = items[0]
        
        try:
            a_track_ids.index(track['id'])
            #print('Found: '+track['name'])
        except:
            # #add to the list
            # sp.playlist_add_items(playlist_id='2CE0LjqBpPFqdv2CnToUIh', items=['spotify:track:'+track['id']+''], position=None)
            # a_track_ids.append(track['id'])
            print('***Added: '+track['name'])


with open("playlist_track_ids.json", "w") as outfile: 
    json.dump(a_track_ids, outfile)

HabAPP fail, cron win

Trying to make python work for OpenHabian rules…

Notes

  • Used the openhabian cli to install HabAPP.
  • The service didn’t start: ModuleNotFoundError: No module named ‘pydantic’
  • I knew I would need curl so…
pip3 install pydantic
sudo systemctl start habapp.service
sudo systemctl status habapp.service

The service still didn’t start. Is HabAPP running in a venv?

pip3 remove pydantic

I determined from the HabAPP documentation that it might run in a venv

openhabian@openhabian:/opt/habapp $ source ./bin/activate
pip3 install pydantic
sudo systemctl start habapp.service
sudo systemctl status habapp.service

Status now said I was missing a different module, EasyCo, and on I went installing and testing…

pip3 install EasyCo
pip3 install eascheduler
pip3 install stackprinter
pip3 install watchdog
pip3 install paho-mqtt
pip3 install aiohttp
pip3 install aiohttp_sse_client
pip3 install immutables
pip3 install bidict

And finally it worked! I was able to list the packages that are installed.

(habapp) openhabian@openhabian:/opt/habapp $ sudo systemctl status habapp.service
● habapp.service - HABApp
   Loaded: loaded (/etc/systemd/system/habapp.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2022-11-12 16:03:56 GMT; 2s ago
     Docs: https://habapp.readthedocs.io
 Main PID: 16102 (habapp)
    Tasks: 7 (limit: 4915)
   CGroup: /system.slice/habapp.service
           └─16102 /opt/habapp/bin/python3 /opt/habapp/bin/habapp -c /etc/openhab/habapp

Nov 12 16:03:56 openhabian systemd[1]: Started HABApp.
(habapp) openhabian@openhabian:/opt/habapp $ pip3 list
Package            Version
------------------ -------
aiohttp            3.8.3
aiohttp-sse-client 0.2.1
aiosignal          1.3.1
astral             2.2
async-timeout      4.0.2
asynctest          0.13.0
attrs              22.1.0
bidict             0.22.0
charset-normalizer 2.1.1
EAScheduler        0.1.7
EasyCo             0.2.3
frozenlist         1.3.3
HABApp             0.31.2
idna               3.4
immutables         0.19
multidict          6.0.2
paho-mqtt          1.6.1
pendulum           2.1.2
pip                22.3.1
pkg_resources      0.0.0
pycurl             7.45.1
pydantic           1.10.2
python-dateutil    2.8.2
pytz               2022.6
pytzdata           2020.1
ruamel.yaml        0.17.21
ruamel.yaml.clib   0.2.7
setuptools         65.5.1
six                1.16.0
stackprinter       0.2.9
typing_extensions  4.4.0
voluptuous         0.13.1
watchdog           2.1.9
yarl               1.8.1

I then endlessley faffed about with no success, watching the log with tail -f and duckduckgoing until I found this page which told me it was broken in OH3.3!! I went back in to the cli and removed HabAPP.

Back to plan A then. I will set up a venv and script to make it work with cron. I already have the script. Should have done this ages ago. All it does is tell me the kWh yesterday as a proof of concept. I already have an Item set up with the number.

import json
import pycurl
import certifi
from io import BytesIO
from openhab import OpenHAB

buffer = BytesIO()
c = pycurl.Curl()
c.setopt(c.URL, 'https://api.octopus.energy/v1/electricity-meter-points/xxxxxxxx/meters/xxxxxxxxxxxxxx/consumption/')
c.setopt(c.USERPWD,'xxxxxxxxxxxxx:')
c.setopt(c.WRITEDATA, buffer)
c.setopt(c.CAINFO, certifi.where())
c.perform()
c.close()

body = buffer.getvalue()
usage = json.loads(body.decode('iso-8859-1'))
# Body is a byte string.
# We have to know the encoding in order to print it to a text file
# such as standard output.
count = 0
yesterday = 0
for x in usage["results"]:
    yesterday = yesterday + x["consumption"]
    count = count + 1
    #print(count,x["consumption"])
    if count == 48:
        break
yesterday = round(yesterday,2)

base_url = 'http://openhabian:8080/rest'
openhab = OpenHAB(base_url)

# fetch all items
items = openhab.fetch_all_items()
items['Yesterday_kWh'].update(str(yesterday) + 'kWh')

And schedule that with cron by making a script to call it that has the full path to the venv inside calling the main.py

0 7 * * * /home/openhabian/projects/energy/energy.py