Community

You need to log in to create posts and topics.

Creating "bin" compatible image files

I noticed that all of your images are in ".bin" format under the /usr/bin/img directory, and I'm wondering what tool you are using to convert those images, and/or whether the card manager can use other image types than this "bin" format (which, I assume is just RGB triplets in order, probably with a height/width header.)

 

One other thing, since I'm trying to build a card, how do you register the "loop" function to get a card to update. I copied the weather card, but the loop function doesn't seem to get called at all after I start my card, with the same setup.

Also, is there a way to make a text element a different color?

And, finally, when I use the same HTTP restful-type request, I get a segmentation fault during the get. Any reason for this? It is an HTTPS request. Is the SSL client not supported?

Any chance of an answer on these? I have a card set up for doing cyber-coin price tracking and stock-market price tracking, but without the update loop, it's pretty much useless.

Any help would be appreciated. I know you guys are hard at work, but I was hoping that this would be a more collaborative process.

 

Yep, you're correct, it's RGB565 triplets in order. We're working on an online image converter and hope to release it in the next few days. We'll let you know as soon as it's up!

Regarding your custom card, as long as you have a function named loop, it will be executed by Onion RunTime (ort). If you don't mind sharing your code and terminal output will take a look at it.

 

 

Here's the code for the coin-card. As you can see, I have a "loop()" function, but it's never called.

var cardInfo = {
    id: -1,
    responseTopic: '/coinTickerCard_' + getEpochMillis(),
    // bgColor: 0xc44569,
    bgColor: 0x0,
    params: {
        symbols: [
            {
              symbol: "BTC",
              currency: "USD",
              elementId: 2
            },
            {
              symbol: "ETH",
              currency: "USD",
              elementId: 5
            },
            {
              symbol: "XRP",
              currency: "USD",
              elementId: 8
            },
            {
              symbol: "LTC",
              currency: "USD",
              elementId: 11
            },
            {
              symbol: "BCH",
              currency: "USD",
              elementId: 14
            },
            {
              symbol: "EOS",
              currency: "USD",
              elementId: 17
            }
          ],
        prevUpdate: 0,
        updateInterval: 60*1000 // 60 Seconds
    }
}

// definitions for the program
var elementId = {
    cardTitle: 0,
    creativeCommonsNotice: 1
};


function createCard () {
    var cardObj = generateNewCardObj(cardInfo.bgColor, cardInfo.responseTopic);
    var prices = null; // getCoinPrices(cardInfo.params.symbols);
    // title card
    cardObj.elements.push(generateTextElement(
                            elementId.cardTitle,
                            'Coin Prices',
                            30,
                            0, 12, 'center')
                        );

    // title card
    cardObj.elements.push(generateTextElement(
                            elementId.creativeCommonsNotice,
                            'Data from https://www.cryptocompare.com',
                            10,
                            0, 245, 'center')
                        );
    var i;
    for ( i = 0; i < cardInfo.params.symbols.length; i++ )
    {
      var line = 48 + (i * 18 );
      cardObj.elements.push(generateTextElement(
          cardInfo.params.symbols[i].elementId,
          cardInfo.params.symbols[i].symbol,
          20,
          0, line
        )
      );
      var price = '$x.xx';
      var change = '+x%';
      if ( prices )
      {
        price = prices[i].priceVal;
        change = prices[i].changeVal;
      }
      cardObj.elements.push(generateTextElement(
          cardInfo.params.symbols[i].elementId + 1,
          price,
          20,
          0, line, 'center'
        )
      );
      cardObj.elements.push(generateTextElement(
          cardInfo.params.symbols[i].elementId + 2,
          change,
          20,
          0, line, 'right'
        )
      );
    }

    // init the card
    initCard(JSON.stringify(cardObj));
}

function updatePrices () {
    var updateObj = generateUpdateCardObj(cardInfo.id);
    var prices = getCoinPrices( cardInfo.params.symbols );

    if (prices !== null) {
        var i;
        for ( i=0; i < prices.length; i++ )
        {
            updateObj.elements.push(generateElementUpdate(
                                    cardInfo.params.symbols[i].elementId + 1,
                                    prices[i].priceVal )
                                );
            updateObj.elements.push(generateElementUpdate(
                                    cardInfo.params.symbols[i].elementId + 2,
                                    prices[i].changeVal )
                                );
        }
        updateCard(JSON.stringify(updateObj));
        return true;
    }

    return false;
}

function setup() {
    connect('localhost', 1883, null, function () {
        subscribe('/cardResponse', function () {
            createCard();
        });
    });
}

function loop() {
    // return if card not initialized
    if (cardInfo.id < 0) return;

    // update prices on interval
    if ((new Date - cardInfo.params.prevUpdate) > cardInfo.params.updateInterval)
    {
        cardInfo.params.prevUpdate = new Date;
        updatePrices();
    }
}

function onInput(e) {
    if (typeof e.source !== 'undefined' && typeof e.payload !== 'undefined' ) {
        print('input! input source: ' + e.source + ', value: ' + e.payload);
    }
}

function onMessage(e) {
    if (typeof e.topic !== 'undefined' && typeof e.payload !== 'undefined' ) {
        print('message! topic: ' + e.topic + ', value: ' + e.payload);
        switch (e.topic) {
            case '/cardResponse':
                cardInfo = handleCardResponseMessage(cardInfo, e.payload);
                break;
            default:
                break;
        }
    }
}



function buildCoinUrl (symbols) {
  var syms = "";
  var curs = "";
  var i;
  for ( i=0; i < symbols.length; i++ )
  {
    if ( i > 0 )
      syms += ",";
    syms += symbols[i].symbol
    if ( ! curs.includes( symbols[i].currency ) )
    {
      if ( i > 0 )
         curs += ",";
      curs += symbols[i].currency;
    }
  }

	var url = 'https://min-api.cryptocompare.com/data/pricemultifull?fsyms=' + syms + '&tsyms=' + curs + '&extraParams=ObooSmartClockTicker';

	return url;
}

function getCoinPrices (symbols) {
    print('getting coin prices');
    var result = httpRequest({
        method: 'GET',
        url: buildCoinUrl(symbols)
    });

    if (result) {
        print(result);
	var jsonResult;
	try {
	    jsonResult = JSON.parse(result);
	} catch(e) {
	    print(e); // error in the above string!
            print(result);
            return null;
        }

        var priceObj = [];
        var displayObj = jsonResult['DISPLAY'];

        if ( displayObj )
        {
            var i;
            for ( i =0; i < symbols.length; i++ )
            {
                 print( symbols[i].symbol );
                 var tickerObj = displayObj[symbols[i].symbol];
                 print( symbols[i].currency );
                 var tickerCurrency = tickerObj[symbols[i].currency];
                 var price = tickerCurrency['PRICE'];
                 var change = tickerCurrency['CHANGEPCTDAY'];

                 var subObj = { 'priceVal': price, 'changeVal': change + "%" }
                 priceObj.push(subObj);
            }
        }
        return priceObj;
    }
    else {
        print( "Received no result from price check.");
	return null;
    }
}


 

When I run the card, I now see "loop" being called, but it still seg-faults on the HTTPS call.

root@Oboo-Clock-5088:~# /usr/bin/ort /usr/bin/js/coin-ticker.js 
ERROR: cannot open file '/usr/bin/./js/lib.js'
filename is absolute!
connecting to message queue at localhost:1883, clientId is 'aaacccbcaa', ptr is 0
Initializing mqtt connection to localhost:1883
message queue initialized (0)
subscribe: '/cardResponse'
Subscribe to topic '/cardResponse' successful
Subscribed (mid: 1): 0
initCard: '{"cmd":"new_card","bg_color":0,"responseTopic":"/coinTickerCard_1534209817188","elements":[{"id":0,"type":"text","value":"Coin Prices","position":{"x":0,"y":12,"align":"center"},"size":30},{"id":1,"type":"text","value":"Data from https://www.cryptocompare.com","position":{"x":0,"y":245,"align":"center"},"size":10},{"id":2,"type":"text","value":"BTC","position":{"x":0,"y":48},"size":20},{"id":3,"type":"text","value":"$x.xx","position":{"x":0,"y":48,"align":"center"},"size":20},{"id":4,"type":"text","value":"+x%","position":{"x":0,"y":48,"align":"right"},"size":20},{"id":5,"type":"text","value":"ETH","position":{"x":0,"y":66},"size":20},{"id":6,"type":"text","value":"$x.xx","position":{"x":0,"y":66,"align":"center"},"size":20},{"id":7,"type":"text","value":"+x%","position":{"x":0,"y":66,"align":"right"},"size":20},{"id":8,"type":"text","value":"XRP","position":{"x":0,"y":84},"size":20},{"id":9,"type":"text","value":"$x.xx","position":{"x":0,"y":84,"align":"center"},"size":20},{"id":10,"type":"text","value":"+x%","position":{"x":0,"y":84,"align":"right"},"size":20},{"id":11,"type":"text","value":"LTC","position":{"x":0,"y":102},"size":20},{"id":12,"type":"text","value":"$x.xx","position":{"x":0,"y":102,"align":"center"},"size":20},{"id":13,"type":"text","value":"+x%","position":{"x":0,"y":102,"align":"right"},"size":20},{"id":14,"type":"text","value":"BCH","position":{"x":0,"y":120},"size":20},{"id":15,"type":"text","value":"$x.xx","position":{"x":0,"y":120,"align":"center"},"size":20},{"id":16,"type":"text","value":"+x%","position":{"x":0,"y":120,"align":"right"},"size":20},{"id":17,"type":"text","value":"EOS","position":{"x":0,"y":138},"size":20},{"id":18,"type":"text","value":"$x.xx","position":{"x":0,"y":138,"align":"center"},"size":20},{"id":19,"type":"text","value":"+x%","position":{"x":0,"y":138,"align":"right"},"size":20}]}'
Message arrived to topic: /cardResponse, message is 103 chars long
recvMessage: payload is a string, converting...
message! topic: /cardResponse, value: {"cardId":5,"attention":"/coinTickerCard_1534209817188","action":"create","success":true}
Assigning card its id: 5
native setNightLight: 0x000000
getting coin prices
url: https://min-api.cryptocompare.com/data/pricemultifull?fsyms=BTC,ETH,XRP,LTC,BCH,EOS&tsyms=USD&extraParams=ObooSmartClockTicker
method: GET
Message arrived to topic: /cardResponse, message is 47 chars long
recvMessage: payload is a string, converting...
message! topic: /cardResponse, value: [object Object]
Card has become active: 5
native setNightLight: 0x000000
Segmentation fault
root@Oboo-Clock-5088:~#

 

I also see this on the mosquitto message queue at the same time:

/cardResponse "{\"cardId\":5,\"attention\":\"/coinTickerCard_1534209817188\",\"action\":\"create\",\"success\":true}"
/set {"cmd":"nightlight", "value":"0x000000"}
/cardResponse {"cardId":5, "action":"select", "success":true}
/set {"cmd":"nightlight", "value":"0x000000"}
undefined undefined
/status {"cmd":"update","elements":[{"type":"battery","value":3}]}

 

Here is the image convertor tool as promised  https://getoboo.com/image-converter.  Take a look and let us know how it works for you.

Thanks for sharing your code. We will give it a try in a bit.

Did you guys ever get to test this out?

@jnaujok

I finally got to test your program. First of all good job making it 🙂

The cause of the segmentation fault is buffer overflow on the http request. Currently the http request buffer size is set to 8192 Characters. We will look into expanding the buffer size in future software releases. In the mean time you can get around the problem by breaking the request into multiple ones and everything should work.

Here I took out BCH from your original list and the card works as expected.

 

 

Awesome -- glad it was something simple.

I guess I can break it into multiple calls (one per coin) and build it out. I know there were people requesting this sort of functionality on the Kickstarter comments.