# Lookup missing cover arts & artist info from lastFM

**URL:** <https://community.openhab.org/t/lookup-missing-cover-arts-artist-info-from-lastfm/34063>\
**Category:** Tutorials & Examples\
**Tags:** squeezebox, rules, examples\
**Created:** [September 9, 2017, 5:39pm UTC](https://community.openhab.org/t/lookup-missing-cover-arts-artist-info-from-lastfm/34063 "2017-09-09T17:39:33Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![patrik\_gfeller](https://community.openhab.org/user_avatar/community.openhab.org/patrik_gfeller/32/118631_2.png) [@patrik\_gfeller](https://community.openhab.org/u/patrik_gfeller)\
**Post date:** [September 9, 2017, 5:39pm UTC](https://community.openhab.org/t/lookup-missing-cover-arts-artist-info-from-lastfm/34063/1 "2017-09-09T17:39:34Z")

</div>

Hi all,

as not all music in my library has cover arts I decided to try to dynamically get the cover image and some artist info for the playing album:

![](https://community-openhab-org.s3-eu-central-1.amazonaws.com/original/2X/3/3422500de7f4dcfb07be4b7b33f224828f2703d3.png)

As usual, not an absolute step-by-step tutorial, but an “inspiration” 🙂 … will be happy to add additional details if required.

```auto
Webview url="/static/Visualization/CoverArt.html" height=6

```

> **Utility .js to get data from OH via REST**
>
> ```javascript
> // ***
> // * Required definitions:
> // * - var baseURL = "../";
> // *
> // ***
> // * Required API
> // * - Google jQuery: https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
> // * - jQuery CSV: https://github.com/evanplaice/jquery-csv
> // * - date.js: http://www.datejs.com/
> // ***
> 
> function GetGroupItemNames(groupItem) {
> var groupUrl = baseURL.concat("rest/items/").concat(groupItem);
> var groupData = GetData(groupUrl);
> var items = [];
> 
> groupData.members.forEach(function (item) {
> items.push(item.name);
> });
> 
> return items;
> }
> 
> function GetOpenHABHistory(item, days, serviceId) {
> var csv = GetOpenItemHABHistoryCSV(item, days, serviceId);
> var arrayData = $.csv.toArrays(csv, {
> onParseValue: $.csv.hooks.castToScalar
> });
> 
> return arrayData;
> }
> 
> function GetData(itemUrl) {
> var itemValue = null;
> // http://api.jquery.com/jquery.getjson/
> $.ajax({
> // contentType: 'text/plain',
> contentType : 'application/json; charset=utf-8',
> // dataType : 'json',
> url: itemUrl,
> data: {},
> async: false,
> success: function (data) {
> if (data != "NULL") {
> itemValue = data;
> }
> }
> });
> 
> return itemValue;
> }
> 
> // JSON to CSV Converter
> function ConvertToCSV(objArray) {
> var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
> var str = '';
> 
> for (var i = 0; i < array.data.length; i++) {
> var line = '';
> for (var index in array.data[i]) {
> if (line !== '') line += ',';
> 
> line += array.data[i][index];
> }
> 
> str += line + '\r\n';
> }
> 
> return str;
> }
> 
> function GetOpenHABItemState(item) {
> var itemUrl = baseURL.concat("rest/items/").concat(item).concat("/state/");
> return GetData(itemUrl);
> }
> 
> function GetOpenHABItem(item) {
> var itemUrl = baseURL.concat("rest/items/").concat(item);
> return GetData(itemUrl);
> }
> 
> function GetOpenHABItemIntValue(item) {
> return Math.round(GetOpenHabItemState(item));
> }
> 
> function GetOpenHABItemHistoryJSON(item, days = 1, service = "rrd4j") {
> var jsonData = null;
> // var numberOfMilliseconds = 86400 * 1000 * days;
> 
> var startTimeObject = (new Date()).addDays(days * -1);
> // var endTimeObject = new Date();
> var _month = startTimeObject.getMonth() + 1;
> var _starttime = startTimeObject.getFullYear() + "-" + _month + "-" + startTimeObject.getDate() + "T" + startTimeObject.getHours() + ":" + startTimeObject.getMinutes() + ":" + startTimeObject.getSeconds();
> // var _endtime = endTimeObject.getFullYear() + "-" + endTimeObject.getMonth() + "-" + endTimeObject.getDate() + "T" + endTimeObject.getHours() + ":" + endTimeObject.getMinutes() + ":" + endTimeObject.getSeconds();
> 
> var itemUrl = baseURL.concat("rest/persistence/items/").concat(item);
> itemUrl = itemUrl.concat("?serviceId=" + service);
> 
> if (days != 1) {
> itemUrl = itemUrl.concat("&starttime=" + _starttime);
> }
> // itemUrl = itemUrl.concat("&endtime=" + _endtime);
> 
> jsonData = GetData(encodeURI(itemUrl));
> return jsonData;
> }
> 
> function GetOpenItemHABHistoryCSV(item, days = 1, service = "rrd4j") {
> var jsonData = GetOpenHABItemHistoryJSON(item, days, service);
> return ConvertToCSV(jsonData);
> }
> 
> function GetParameter(parameterName) {
> var result = null,
> tmp = [];
> location.search.substr(1).split("&")
> .forEach(function (item) {
> tmp = item.split("=");
> if (tmp[0] === parameterName) {
> result = decodeURIComponent(tmp[1]);
> }
> });
> return result;
> }
> 
> function DOMSetElementHeight(elementId, height) {
> var pageElement = document.getElementById(elementId);
> pageElement.style.height = height + "px";
> }
> 
> function DOMSetElementWidth(elementId, width) {
> var pageElement = document.getElementById(elementId);
> pageElement.style.width = width + "px";
> }
> 
> var WINDOWS_1252 = '\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€�‚ƒ„…†‡ˆ‰Š‹Œ�Ž��‘’“”•–—˜™š›œ�žŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ';
> 
> function Windows1252ToUTF8(binaryString) {
> var text = '';
> 
> for (var i = 0; i < binaryString.length; i++) {
> text += WINDOWS_1252.charAt(binaryString.charCodeAt(i));
> }
> 
> return text;
> }
> 
> ```

> **The .html to display the image**
>
> ```html
> <html>
> 
> <head>
> <title>Cover art</title>
> 
> <link rel="stylesheet" type="text/css" href="../css/visualizationStyle.css">
> 
> <script type="text/javascript">
> var baseURL = "../../../";
> var pageWidth = window.innerWidth;
> var pageHeight = window.innerHeight;
> 
> </script>
> <script type="text/javascript" src="../javascript/openHAB.js"></script>
> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
> 
> <script type="text/javascript">
> function update() {
> var url = GetOpenHABItemState("ItemCoverArtURL");
> var artistInformation = GetOpenHABItemState("ItemArtistInformation");
> 
> var coverArtElement = document.getElementById("CoverArt");
> var artistInfoElement = document.getElementById("ArtistInformation")
> 
> try {
> var coverURL = unescape(JSON.parse(url));
> if (coverURL == "") {
> coverURL = "http://192.168.0.73:9000/music/current/cover.jpg";
> }
> coverArtElement.src = coverURL;
> } catch (err) {
> coverArtElement.src = unescape(url);
> }
> try {
> artistInformation = unescape(JSON.parse(artistInformation));
> artistInformation = artistInformation.replace(/(?:\r\n|\r|\n)/g, '<br />');
> } catch (err) {}
> 
> // artistInformation = artistInformation.substr(0, artistInformation.indexOf("User-contributed text"));
> artistInfoElement.innerHTML = artistInformation;
> 
> setTimeout(update, 10000);
> }
> 
> $(document).ready(function() {
> update();
> });
> 
> </script>
> 
> <style>
> img#CoverArt {
> height: 190px;
> width: 190px;
> -moz-box-shadow: -10px 10px 40px -8px;
> -webkit-box-shadow: -10px 10px 40px -8px;
> box-shadow: -10px 10px 40px -8px;
> -moz-border-radius: 20px;
> -webkit-border-radius: 20px;
> -khtml-border-radius: 20px;
> border-radius: 20px;
> float: right;
> margin-right: 8px;
> border: 4px solid black;
> margin-left: 10px;
> }
>         
> p#ArtistInformation {
> color: gray;
> text-indent: 38px;
> font-style: italic;
> margin-top: 10px;
> }
> 
> </style>
> 
> </head>
> 
> <body>
> <div>
> <img id="CoverArt" />
> </div>
> <div>
> <p id="ArtistInformation"></p>
> </div>
> </body>
> 
> </html>
> 
> ```

> **The rules**
>
> ## Artist info
> 
> ```php
> rule UpdateArtistSummary
> when
> Item ItemRadioAlbum changed
> or Item ItemRadioArtist changed
> or Item ItemRadioTitle changed
> or Item ItemSqueezeSelectedRadioStation changed
> then
> val String _url = "http://ws.audioscrobbler.com/2.0/";
> val String _commandAlbum = "?method=artist.getinfo";
> val String _artist = ItemRadioArtist.state.toString
>     
> if (_artist != null && !_artist.isEmpty()) {
> val String _artistEncoded = URLEncoder::encode(_artist, 'UTF-8')
> val String _request = _url + _commandAlbum 
> + "&api_key=" + lastFMAPIKey 
> + "&artist=" + _artistEncoded
> + "&format=json"
>                                  
> val String _json = sendHttpGetRequest(_request);
>       
> var String _artistInfo = transform("JSONPATH", "$..bio.summary", _json) 
> //.content to get more details
>        
> ItemArtistInformation.postUpdate(_artistInfo)                       
> } else {
> ItemArtistInformation.postUpdate("")
> }
>     
> end
> 
> ```
> 
> ## Cover
> 
> ```php
> 
> rule UpdateRadioCover
> when
> Item ItemRadioAlbum changed
> or Item ItemRadioArtist changed
> or Item ItemRadioTitle changed
> or Item ItemSqueezeSelectedRadioStation changed
> then
> val String _url = "http://ws.audioscrobbler.com/2.0/";
> val String _commandAlbum = "?method=album.getinfo";
> val String _commandTitle = "?method=track.getInfo";
> val String _album = ItemRadioAlbum.state.toString
> val String _title = ItemRadioTitle.state.toString
> val String _artist = ItemRadioArtist.state.toString
>     
> var String _albumURL = "http://192.168.0.73:9000/music/current/cover.jpg";
> if ((_artist != null && !_artist.isEmpty()) && (_title != null && !_title.isEmpty())) {
> val String _artistEncoded = URLEncoder::encode(_artist, 'UTF-8')
> val String _titleEncoded = URLEncoder::encode(_title, 'UTF-8')
>       
> val String _request = _url + _commandTitle 
> + "&api_key=" + lastFMAPIKey 
> + "&artist=" + _artistEncoded
> + "&track=" + _titleEncoded
> + "&format=json"
> // println(_request)
> val String _json = sendHttpGetRequest(_request);
> var String _lastFMAlbumURL = transform("JSONPATH", "$..image[3].#text", _json)
> _lastFMAlbumURL = _lastFMAlbumURL.replace("[","")
> _lastFMAlbumURL = _lastFMAlbumURL.replace("]","")
> if (_lastFMAlbumURL != null && !_lastFMAlbumURL.isEmpty()) {
> println(_lastFMAlbumURL)
> _albumURL = _lastFMAlbumURL;
> }
> } else if ((_artist != null && !_artist.isEmpty()) 
> && (_album != null && !_album.isEmpty())) {
> val String _artistEncoded = URLEncoder::encode(_artist, 'UTF-8')
> val String _albumEncoded = URLEncoder::encode(_album, 'UTF-8')
>        
> val String _request = _url + _commandAlbum 
> + "&api_key=" + lastFMAPIKey 
> + "&artist=" + _artistEncoded
> + "&album=" + _albumEncoded
> + "&format=json"
>        
> val String _json = sendHttpGetRequest(_request);
> var String _lastFMAlbumURL = transform("JSONPATH", "$..image[3].#text", _json)
> _lastFMAlbumURL = _lastFMAlbumURL.replace("[","")
> _lastFMAlbumURL = _lastFMAlbumURL.replace("]","")
> if (_lastFMAlbumURL != null && !_lastFMAlbumURL.isEmpty()) {
> _albumURL = _lastFMAlbumURL;
> }
> } else if (ItemSqueezeSelectedRadioStation.state >= 0) {
> _albumURL = "/static/img/radio/" + ItemSqueezeSelectedRadioStation.state + ".png"
> } else if (ItemSqueezeSelectedPodcast.state >= 0) {
> _albumURL = "/static/img/podcast/" + ItemSqueezeSelectedPodcast.state + ".png"
> }
> ItemCoverArtURL.postUpdate(_albumURL)
> end
> 
> ```

Moderators: Please feel free to wikify this article.

with kind regards,  
Patrik

---

<div class="post-metadata">

**Author:** ![rlkoshak](https://community.openhab.org/user_avatar/community.openhab.org/rlkoshak/32/75251_2.png) [@rlkoshak](https://community.openhab.org/u/rlkoshak)\
**Post date:** [September 10, 2017, 12:45am UTC](https://community.openhab.org/t/lookup-missing-cover-arts-artist-info-from-lastfm/34063/2 "2017-09-10T00:45:58Z")

</div>

Nice. I would expand this to actually add the cover to my library. 😋 Looks great! Thanks for sharing.
