Creating "bin" compatible image files
Quote from jnaujok on August 5, 2018, 12:54 amI 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.)
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.)
Quote from jnaujok on August 5, 2018, 2:00 amOne 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?
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?
Quote from jnaujok on August 12, 2018, 1:44 pmAny 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.
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.
Quote from Zheng Han on August 13, 2018, 4:13 pmYep, 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.
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.
Quote from jnaujok on August 13, 2018, 9:17 pmHere'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; } }
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; } }
Quote from jnaujok on August 13, 2018, 9:26 pmWhen 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}]}
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}]}
Quote from Zheng Han on August 14, 2018, 12:53 pmHere 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.
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.
Quote from jnaujok on August 26, 2018, 1:59 pmDid you guys ever get to test this out?
Did you guys ever get to test this out?
Quote from Zheng Han on September 5, 2018, 10:57 am@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.
@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.
Quote from jnaujok on September 11, 2018, 2:06 pmAwesome -- 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.
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.