OH3 - Rule and widget to display artist meta information from lastFM

I’ve create a small rule to get artist information from lastFM to be displayed in a player widget:


The code to fetch the meta information about the artist (you need a lastFM API key for this to work):

.dsl
import org.openhab.core.model.script.ScriptServiceUtil
import java.net.URLEncoder

val Object _lockArtistMetadataLookup = new Object()

var LoadArtistMetadata = [ String itemPrefix |        
    val artistItem = ScriptServiceUtil.getItemRegistry?.getItem(itemPrefix + "_MediaArtist")
    val summaryItem = ScriptServiceUtil.getItemRegistry?.getItem(itemPrefix + "_ArtistSummary")

    var artist = artistItem.state.toString()    

    // The player is buffering, no artis information available yet.
    if ((artist == "ZPSTR_CONNECTING") 
     || (artist == "ZPSTR_BUFFERING")) {
        return
    }

    if (artist.trim().isEmpty()) {
        return
    } 

    synchronized (_lockArtistMetadataLookup) {      
        val String url = "http://ws.audioscrobbler.com/2.0/"
        val String commandAlbum = "?method=artist.getinfo"

        val String artistEncoded = URLEncoder::encode(artist, 'UTF-8')
        val String request = url + commandAlbum 
                               + "&api_key=<your api key>"
                               + "&artist="  + artistEncoded
                               + "&format=json"

        val String json = sendHttpGetRequest(request)    
        var String artistInfo = transform("JSONPATH", "$..bio.summary", json)         

        if (artistInfo !== null && artistInfo !== "NULL" && !artistInfo.isEmpty()) {
            artistInfo = artistInfo.replaceAll("Read more on Last.fm", "")

            if (artistInfo.trim().startsWith("<a href=")) {
                summaryItem.postUpdate("Keine Information zum Künstler gefunden.")
                return
            }
        } else {
            summaryItem.postUpdate("Keine Information zum Künstler gefunden.")
            return
        }

        if (artistInfo.length > 650) {
            artistInfo = artistInfo.substring(0, 650) + " ..."
        }
        summaryItem.postUpdate(artistInfo.split("<a href").get(0))
    }
]

rule "Lade informationen zum Künstler"
    when
        Item SonosSYMFONISKBuro_MediaArtist changed or
        Item SonosSYMFONISKKuche_MediaArtist changed or
        Item SonosPortFernsehzimmer_MediaArtist changed or
        Item SonosSYMFONISKTechnikraum_MediaArtist changed or
        Item SonosSYMFONISKKeller_MediaArtist changed or
        Item SonosSYMFONISKBad_MediaArtist changed or
        Item SonosSYMFONISKGastezimmer_MediaArtist changed or
        Item SonosSYMFONISKSchlafzimmer_MediaArtist changed
    then        
        LoadArtistMetadata.apply(triggeringItemName.split("_").get(0))
    end

The widget code:

.yml
uid: player_v2
tags: []
props:
  parameters:
    - description: Title for the widget
      label: Static Title
      name: title
      required: false
      type: TEXT
    - description: Player prefix
      label: Player prefix
      name: prefix
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Apr 13, 2021, 5:15:08 PM
component: f7-card
config:
  title: =props.title
  style:
    min-width: 270px
slots:
  default:
    - component: f7-row
      config:
        class: margin display-flex align-items-center
      slots:
        default:
          - component: f7-col
            config:
              width: 100
              xsmall: 100
              small: 100
              medium: 50
              large: 50
              xlarge: 50
            slots:
              default:
                - component: f7-row
                  config:
                    class: '=(items[props.prefix+"CurrentAlbumCoverArt"].state === "NULL")?"display-none" : "- margin-vertical - justify-content-center"'
                  slots:
                    default:
                      - component: oh-swiper
                        config:
                          noBorder: true
                          noShadow: true
                          pagination: true
                          style:
                            - width: 100%
                        slots:
                          default:
                            - component: oh-image
                              config:
                                item: =props.prefix+"_CurrentAlbumCoverArt"
                                style:
                                  - width: 100%
                            - component: oh-link
                              config:
                                style:
                                  padding: 10px
                                textColor: black
                                text: =items[props.prefix+"_ArtistSummary"].state
          - component: f7-col
            config:
              width: 100
              xsmall: 100
              small: 100
              medium: 50
              large: 50
              xlarge: 50
            slots:
              default:
                - component: f7-row
                  config:
                    class: = "display-flex justify-content-center"
                  slots:
                    default:
                      - component: Label
                        config:
                          text: =items[props.prefix+"_MediaArtist"].state || "-"
                          style:
                            white-space: nowrap
                            overflow: hidden
                            font-size: normal
                            font-weight: bold
                            font-style: italic
                - component: f7-row
                  config:
                    class: = "display-flex justify-content-center"
                  slots:
                    default:
                      - component: Label
                        config:
                          text: =items[props.prefix+"_MediaTitle"].state || "-"
                          style:
                            white-space: nowrap
                            overflow: hidden
                            font-size: normal
                            font-weight: bold
                - component: f7-row
                  config:
                    class: = "display-flex justify-content-center"
                  slots:
                    default:
                      - component: Label
                        config:
                          text: =items[props.prefix+"_CurrentAlbum"].state || "-"
                          style:
                            white-space: nowrap
                            overflow: hidden
                            font-size: normal
                            font-style: italic
    - component: f7-row
      config:
        class:
          - justify-content-space-around
          - display-flex
          - align-items-center
          - align-content-stretch
          - margin-top
      slots:
        default:
          - component: f7-icon
            config:
              f7: '=(props.prefix+"_Shuffle") ? "shuffle" : ""'
              size: 20
              color: '=(items[props.prefix+"_Shuffle"].state === "ON") ? "green" : ""'
              style:
                position: relative
                left: +7%
            slots:
              default:
                - component: oh-button
                  config:
                    action: command
                    actionItem: = props.prefix+"_Shuffle"
                    actionCommand: '=(items[props.prefix+"_Shuffle"].state !== "ON") ? "ON" : "OFF"'
                    style:
                      position: absolute
                      width: 100%
                      height: 100%
                      top: 0px
          - component: oh-player-item
            config:
              style:
                width: 150px
              item: =props.prefix+"_MediaControl"
              class:
                - display-flex
                - margin-
                - align-content-stretch
                - align-items-center
                - justify-content-space-around
          - component: f7-icon
            config:
              f7: '=(props.prefix+"_Repeat") ? (items[props.prefix+"_Repeat"].state === "Off") ? "repeat" : (items[props.prefix+"_Repeat"].state === "Track") ? "repeat_1" : "repeat" : ""'
              size: 20
              color: '=(items[props.prefix+"_Repeat"].state === "Queue") ? "green" : (items[props.prefix+"_RepeatMode"].state === "track") ? "green" : ""'
              style:
                position: relative
                left: -8%
            slots:
              default:
                - component: oh-button
                  config:
                    action: command
                    actionItem: = props.prefix+"_Repeat"
                    actionCommand: '=(items[props.prefix+"_Repeat"].state === "Off") ? "Track" : (items[props.prefix+"_Repeat"].state === "Track") ? "Queue": "Off"'
                    style:
                      position: absolute
                      width: 100%
                      height: 100%
                      top: 0px
    - component: f7-row
      config:
        class:
          - justify-content-space-around
          - display-flex
          - align-items-center
          - align-content-stretch
          - margin-top
      slots:
        default:
          - component: f7-card
            config:
              noShadow: true
              class: margin display-flex align-items-center
              style:
                height: 20px
                fontSize: 20px
                width: 100%
            slots:
              default:
                - component: f7-icon
                  config:
                    f7: speaker_3
                    class: margin-horizontal margin
                    size: 25
                - component: oh-slider
                  config:
                    label: true
                    style:
                      width: 75%
                      --f7-range-knob-color: rgba(122,122,122,0.8)
                      --f7-range-bar-size: 12px
                      --f7-range-bar-border-radius: 6px
                      --f7-range-knob-size: 16px
                      --f7-range-bar-bg-color: rgba(122,122,122,0.2)
                      --f7-range-bar-active-bg-color: linear-gradient(to right, rgba(255,255,255,0), rgba(255,255,255,0.6))
                      --f7-range-knob-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3)
                    item: =props.prefix+"_Volume"

As I’m using a lot of snippets from the forum I hope this will be useful to someone :slight_smile: .

1 Like

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.