A while back I wrote an article on how to Cancel long running SQL Command in ASP.NET WebForm application
Webucator ASP.NET training was kind enough to turn it into video-lesson. Enjoy!
A while back I wrote an article on how to Cancel long running SQL Command in ASP.NET WebForm application
Webucator ASP.NET training was kind enough to turn it into video-lesson. Enjoy!
I’ve recently updated code for Cobblestyle Pebble Watchface to take advantage of very cool geocoding service called Nominatim by Open Street Maps.
Nominatim is used in two places: Direct lookup is used in watchface’s config page to lookup coordinates of a place by its name for custom location setting; reverse lookup is used to lookup location name by its coordinates to display name on actual watchface.
It was working fine – on Pebble watches connected to Android phones. It was failing miserably on iOS, so iPhone Pebble users were getting neither location nor weather updates. And it was pretty puzzling for a while until I obtained logs from running watchface thanks to invaluable help from Robin.
Turned out iPhone Pebble app was plain simple blocked by Nominatim service, every attempt to retreive location resulted in message being sent back “You have violated acceptable policy”. Which was kinda surprising since I just started using the service. When I contacted Nominatim support, they told me that apparently some Pebble app running from iPhone abused the service pretty badly, running hundreds of requests per second. And since the only way they can detect requesting app is by it’s User Agent string – all apps spotting iPhone Pebble UA were blocked.
Support suggested to set UA string specific to the app so it could be easily identifiable. Standard approach to set headers on xmlHttpRequest
object is .setRequestHeader(..)
. Unfortunately by many browsers and clients it is considered unsafe to spoof UA via request headers. Fortunately iOS allows that, so all I have to do is catch and ignore erros in other clients. Basically this line of code solved the issue:
try {xhr.setRequestHeader("User-Agent", "Cobblestyle Pebble Watchface");} catch(e){}
Thanks to this as of version 2.19 Cobblestyle watchface correctly displays weather and location information. Yay.
First things first. DISCLAMER: Everything described here is a hack upon a crude hack and most likely, barring a divine intervention, won’t work in final product. And I apologize in advance to Pebble dev team if my attempts at “hacking” seem silly. Now to business. Pebble SDK offers very cool framebuffer API that allows developers to address display memory of the watch directly. This makes possible creation of many cool special effects (matter of fact EffectLayer library uses framebuffer extensively).
Rocky.js is JavaScript incarnation of Pebble SDK and it made me wonder whether it offers framebuffer access. Turned out it is hidden, but it’s there. At least at the latest commit at the time of this article it is. If you take a look at source file html-bindings.js you will see that binding function looks something like this:
Rocky.bindCanvas = function(canvas, options) { //... var framebufferPixels = new Uint8Array(module.HEAPU8.buffer, framebufferPixelPTR, canvasW * canvasH); //... var binding = { //... } //... return binding; };
Rocky.JS is the first step in Pebble journey to run JavaScript directly on the watches (unlike Pebble.JS which runs on your phone). Previously I described how to convert a simple watchface from C to Rocky.js. But that was a static watchface with unchangeable settings.
Here I will show how to create a configurable watchface in Rocky.js similarly how classic SDK faces can be configured. You will be able to reuse your existing config page – and if it was set to work with Pebble emulator as well as real watch – you will reuse it without any changes at all.
First let’s review how classic Pebble SDK calls config page. In PKJS (JavaScript) portion of Pebble code usually there’s a piece like this:
Pebble.addEventListener("showConfiguration", function(e) { Pebble.openURL("http://my.cool.server/pebble/my_cool_config.html"); } );
If user requests config of face/app – this event fires and opens page with configurable options from specified URL. After user modifies settings usually “Save” button is clicked on that page and code similar to this executes:
$('#xbtnSave').click(function () { var location = (decodeURIComponent(getURLVariable('return_to')) || "pebblejs://close#") + encodeURIComponent(JSON.stringify(settings)); document.location = location; })
Here, first we determine which location to redirect config page to. If parameter "return_to
” is passed in query string (here custom function getURLVariable()
is used to extract individual parameters – look it up), so if this parameter is passed – it means config page is called form the emulator and we use it for redirection. Otherwise we use standard "pebblejs://close#"
URL to save settings into real watch. We also take settings
object which has our collective options combined, convert it to string and add to the URL as a parameter. Page then is redirected to resulting URL and Pebble emulator or real watch takes care of processing parameters.
So, how can we (re)use it in a Rocky.js watchface? Continue reading →
I really like my new smart TV from Samsung it has tons of bells and whistles. But one thing I noticed – no matter what I watch – series or movies, streaming or broadcast – picture has a “teleplay” feeling – like the action is happening on stage in the theater. If you recall what later Twilight Zone episodes look like you’d know what I am talking about. Maybe it’s supposed to look like this, but I like “film” feeling more. So I found a setting that restores natural picture look:
Go to your TV menu, then select Picture -> Picture Options -> Auto Motion Plus and turn it off.
I recently got a Roku 4 – at the time of this post the latest and greatest streaming players from Roku family. It comes with many bells and whistles – including ability to connect to 5Ghz WiFi networks. But for the life of me – it could not connect to mine. Player was seeing the SSID of the network, able to connect to wireless, but chocked on joining to LAN. Extensive chat with support lead nowhere – they wanted me to change WAN DNS and many other hoops that achieved nothing. For the record – my router is a dual-band one, and Roku had no problems connecting to 2.4Ghz band. But Internet speed falls dramatically over 2.4Ghz connection and I needed 5Ghz.
Finally I found one thing that worked.
AC connection has 3 bandwidth modes: 20Mhz, 40Mhz, and 80Mhz. My router was set to 80Mhz to take full advantage of 1300 speed. None of my devices had problem with this (including, I might add, my previous Roku 3 player). But apparently Roku 4 couldn’t handle it. But as soon as I switched bandwidth to 40Mhz – boom, instant connection.
Streaming doesn’t suffer from this change, but it does lower LAN speed, so I’d like alternative solution from Roku if possible. Is this a known issue? Would an update fix it?
Recently two Pebble watchfaces I’ve developed based on Paul Joel designes: Clean&Smart and Cobblestyle began to experience weather update issues – as in “weather was not updated at all”. Looking into the issue I found a weird thing: If you set your location manually – weather worked. But automatic weather based on phone location did not.
The way automatic location works is pretty straighforward. First this function is called to determine location:
function getLocation() { navigator.geolocation.getCurrentPosition( locationSuccess, locationError, {timeout: 15000, maximumAge: 60000} ); }
It uses phone location services (GPS, if its available, otherwise network-based location). In case of success it calls locationSuccess
function. And in my tests it always called it, so location was determined successfully. Continue reading →
I’ve encountered a weird issue while working with EffectLayer Library (a visual effect library for Pebble smartwatch). In this particular watchface called Clean & Smart I used “invert” effect which inverts colors of the watchface should the user choose that option in settings. It was working fine when option changed when watchface was loaded/unload and behaved weirdly only in one particular scenario: when you would receive a notification (email, text etc.) and then dismiss it. Upon coming back from notification to watchface invert effect would only partially cover the watchface (as seen on the screenshot).
I don’t know exactly what was happening, but had a theory. Continue reading →
“Tick tock, goes the clock, And Now what shall we play?”.
Pebble smartwatch is an amazing piece of hardware with no less amazing software to support it. Pebble appstore boasts huge variety of watchfaces from intricately carved art pieces to simplicity personified. And the apps, my gods the apps! You want to track your sleep, count swimming stokes, automate your home – Pebble can do all those things and more. But something was missing. Something that ordinary mechanical clocks could do since the dawn of time.
Tick tock, goes the clock, And then what shall we see?
Continue reading →
SDK 3.x for Pebble Time smartwatch offers cool and very convenient set of functions to create animation from your existing GIF or MP4 via APNG support. APNG is an obscure “Animated PNG” format (at the time of the post only Mozilla Firefox supports it) but it’s very powerful and can store animation in much more compressed format than traditional animated GIF, so Pebble chose it for a reason. So if you have a GIF, convert it to APNG with Gif2Apng (or if you have a video, convert MP4 to GIF first and then to APNG) and you’re ready to use it on Pebble Time. Just keep the size in check, since Pebble has to load entire APNG sequence in memory, try not to go overboard. The first video is showing animation from my “Vortex” watchface using this approach on Pebble Time.
But what about original classic Pebbles? Eventually they will get firmware 3.x and SDK 3.x support and with that APNG functions among other advantages, but at the time of this writing it is still hazy when this is going to happen. But where there’s a will there’s a way – you can still use your MP4/GIF source for animation it’s just a bit more tricky. Instead of dealing with a single APNG file as your resource and relying on Pebble firmware to draw the frames you will need to help it a little.
First you will need to split your source into individual frames, for example using this service. Yes, you will be dealing with individual frames, so don’t go creating a Hollywood blockbuster. But don’t fret, it’s a bit more manual work, but you won’t have to hand-crank the moving pictures all the way.
Continue reading →