Friday, June 19, 2015

Bluetooth Switch IOGEAR KeyShair GKMB02


I've been searching for a bluetooth switch for a year or two. A simple gadget that would allow me to use one keyboard and trackball for multiple devices and would allow me to switch between devices with a simple hotkeys. I already have bought  Logitech K810 keyboard that has that functionality but it's only for a keyboard. As a mouse I use a trackball because it's so much faster to use and only decent wireless trackball is Orbit from Kensington but it has it's own dongle and therefore tied to only one device.

Where are you?

Finally I found what I was looking for:
MultiBlue Dongle USB BlueTooth V3.0 HiD PC Keyboard and Mouse Switch for Android, iPhone and iPad (BT300KMS)
I then googled a bit more and found the same device with different names:
EASYBLUE BLUETOOTH KEYBOARD & MOUSE DONGLE FOR ANDROID, IPHONE & IPAD
IOGEAR KeyShair Bluetooth Keyboard and Mouse for Smartphones and Tablets (GKMB02)


It seems the original maker is Zaram from South-Korea.
Easyblue - Keyboard/Mouse Sharing Device
The device was launched 21.12.2012, two and a half years ago and I've been looking for a device like this for two years! There might be some need of improving in marketing departments...with these kinds of niche markets it is essential to find the right channels for marketing the product efficiently..The one I bought was Iogears KeyShair.

Installing

The device was easy to install but I had to buy two new BT dongles to get my system working. My host PC's BT dongle was already old and it didn't pair with my Twiddle3 keyboard. So I bought Asus USB-BT400 dongle and there was no problem with pairing anymore. Then I had problems in pairing KeyShair with Lenovo X1 Carbon Touch and read I was not the only one that had problems with Lenovo's bluetooth so I bought a second USB-BT400 for it and it paired with KeyShair effortlessly. I also connected KeyShair with my phone and tablet, no problems with them.


Input lag

I tried to measure additional lag with Human Benchmark - Reaction Time Test
Usb trackball -> Client PC 270ms
Usb trackball -> Host PC -> KeyShair -> Client PC 280ms
So KeyShair does not make much lag, only measured additional +10ms.

Kensington trackball had much more lag:
Kensington -> Host PC -> KeyShair -> Client PC 400ms = +120ms additional lag compared to usb trackball.

Conclusion

What can I say? It works as it should. The best part is I can use my wireless keyboard and Twiddler3 both and learn writing with Twiddler3. If there is a key I don't yet know, I can write it with my Logitech keyboard and then gradually learn all the keys with Twiddler3.
Now I can switch all the input devices with a simple hotkeys.
Twiddler3 also autoconnects with my PC which it does not do with my phone&tablet. KeyShair autoconnects with phone&tablet so I don't have to connect Twiddler3 manually to Android devices anymore.

Wednesday, June 3, 2015

Tulevaisuuden työmatkaliikkumista sähkökäyttöisellä yksipyöräisellä


Tein lyhyen ja hitaaksi leikatun videon tulevaisuuden työmatkaliikkumisesta. Videon tausta-ajatuksena oli Kraftwerkin kappale Autobahn joten pistä se taustalle soimaan :)


Sunday, May 17, 2015

Extreme Contrast Enhancer for Monitors in sunlight!

One word:Shades.

If you like to work outside like me, get shades big enough for the wall behind you.

Paint the other side of shades black, and the other side stays white.


Magic shades in Normal (ECO) mode. Can't see what's on monitor in bright sunlight.


Magic shades in Ex3m Contrast Enhancer (tm) mode.
Notice how the back of Lg monitor changes from black to white when camera adjusts shutter speed.

Now the same treatment to my home theater.

This should also work with window shades. Paint the inside shades in gray color ( not necessarily black). Place LED lights above or under window in that way that when the shades are in 45 degree angle and gray shades are inside and white shades outside, you can see outside even in the evening because the gray shades are not too bright. But from outside you cannot see inside because the LED light is reflected outside from the white shades. All you can see is bright shades.

Tekgear Twiddler3 : yhden käden langaton näppäimistö

Olin syksyllä etsimässa näppäimistöä joka sopisi yhden käden käyttöön ja kuin tilauksesta Tekgear oli samaan aikaan valmistelemassa Twiddlerin julkistamista. Muistan samanlaisia kitaraotteeseen perustuvia näppäimistöjä olleen jo 80-luvulla, mutta silloin tekniikka ei ollut vielä tarpeeksi kehittynyttä.


Twiddler3 ohittaa entiset vajavaisuudet ollen täydellisesti käteensopiva langaton bluetooth näppäimistö. Hinta on hieman korkea 200 euroa, mutta toisaalta tämä sallii täydellisen vapauden kirjoittamispaikasta kun nytkin kirjoitan yhdessä Helsingin rantakadun kahviloista. Kirjaimet luodaan yhden tai useamman näppäimen yhdistelmällä.

 

Ylläolevasta kuvasta näkyy luomani "cheatsheet". Vasemman puolen kirjaimet eivät vaadi kuin yhden näppäimen painamisen mutta keskimmäisiin vaaditaan ylimmän rivin oikea näppäin mukaan sekä oikeanpuolimmaisiin ylemmän rivin keskimmäinen näppäin. Lisäksi olen tehnyt oman konfiguraation missä skandinaaviset näppämet saadaan ylimmän rivin vasemmalla näppäimellä.

Koska näppäimistö poikkeaa niin paljon muista näppäimistöistä vie sen opettelu aikansa, mutta jos sinulla on visio Twiddler3:n mahdollisista käyttötarpeista niin se aika ei ole hukkaanheitettyä.

Twiddler on vapaasti muunneltavissa konfiguraatiotiedostoilla ja näppäinyhdistelmiä on niin suuri määrä että taitojen lisääntyessä voi luoda makroja, jolloin tietty näppäinyhdistelmä voi tuottaa tavuja tai kokonaisia lauseita. Olen tehnyt Twiddler3:een kaksi skriptiä, joilla on helppo luoda uusia konfiguraatioita. Tekgearilla on omakin nettiportaali, jossa voi suunitella näppäinkonfiguuraatioita mutta se ei tue skandinaavisia näppäimiä. Lisäksi se on hieman hidaskäyttöinen, jolloin suurempia muutoksi tehtäessä tekstitiedosto onkin nopeampi tapa. Luomaani tekstiformaattiin voi lisäksi lisätä myös kommentteja sekä näppäimet voi järjestellä haluamaansa järjestykseen mikä helpottaa suunnittelua.

Olen luonut suomenkielisen konfiguraation missä ei ole vielä kaikkia erikoisnäppäimiä mutta peruskirjoittaminen onnistuu jo. Osaan itsekin vasta tavalliset aakkoset, jota sitten laajennan kirjain kerrallaan.
twiddler.cfg skandeille binaarimuodossa

En löytänyt Androidille sovellusta, joka lukisi ääneen kirjoittamani tekstin joten tein sellaisen itse.
Se käyttää Googlen Text-to-speechiä, mutta versio 2:sta, jolloin ei ole saatavissa suomenkielistä ääntämystä vaan teksti luetaan vahvasti americalaisittain ääntäen. Se kuitenkin mahdollistaa pitkienkin tekstien kirjoittamisen ilman että tarvitsee jatkuvasti pitää kännykän näyttöä esillä.
Tekstin voi tarvittaessa laittaa kuulumaan kuulokkeilla, joilloin puheääni ei kuulu muille ympärilläolijoille
TwiddlerWriter

Kirjoitusnopeuteni on parin viikon harjoittelun jälkeen vasta noin puolet tavallisen näppäimistön nopeudesta, mutta vasta nyt olen päässyt kirjoittamaan oikeaa tekstiä kun olen saanut myös skandinaaviset näppäimet käyttöön.

Bussissa kirjoittaminen kannettavalla tai tabletilla on ollut hieman hankalaa bussin liikkuessa joten Twiddlerillä sekin onnistuu ongelmitta. Samoin voisin kuvitella että kahvilat ja terassit ovat oivia käyttökohteita. Käyttöpaikkoja twiddlerillä on kuitenkin paljon etenkin kesän jo ollessa ovella.

Tässä yksi taannoin Nuuksiossa käydessäni.


Tuesday, April 28, 2015

RecordBreaker - Simple Android app for keeping the running pace or breaking speed records.

Simple app for keeping the running pace or breaking speed records.

You enter the target speed and alert levels and the app speaks the difference of current speed to target speed in kilometers/hour. Just put on your bluetooth headset and you have a much cheaper version of Recon HUD.

There are two different alerts, one when you are slower than target and one for faster speeds.
You can set different pitches of speech for both alerts so you can recognize which alert you are hearing.

You can also set "safe zone" around target speed where no readings are read aloud.

Software uses GPS location and haversine formula to calculate speed. Doppler data not used, sorry.
If you set output filename, app also logs the measurements to file.

The app uses no network. Therefore you might need to install first some other app that uses Google Text-to-speech and installs it. I chose the "no network" road that you might feel more safe with app. No ads.

Settings:
UpperFarLimit: Speeds >= TargetSpeed + UpperFarLimit are not read aloud.
UpperPitch: Speech pitch for faster than target speed alerts.
UpperNearLimit: Speeds >= TargetSpeed + UpperNearLimit are read aloud.
TargetSpeed: One setting to set the target speed.
LowerNearLimit: Speeds <= TargetSpeed - UpperNearLimit are read aloud.
LowerPitch: Speech pitch for slower than target speed limits.
LowerFarLimit: Speeds <= TargetSpeed - UpperFarLimit are not read aloud.
Measuring interval: GPS measuring interval in seconds. Depends on your hardware.
Log File: File name for log file. If empty, no log file.
Read Interval: Sets how often alerts are read aloud. When set for instance to 3, every third GPS measurement is read aloud. Every measurement will still be written to screen and to log file.

RecordBreaker

TwiddlerWriter - app for writing memos and email with wireless keyboard like Twiddler3

I wrote a small app for writing texts with only my Twiddler3 and bluetooth headset:

TwiddlerWriter is an app for writing memos or emails with Twiddler one-hand keyboard. Every alphabet or word is read out loud so you don't have to look at your phone while you are writing. You can write while walking or commuting or like me right now sitting in my balcony in sunlight while having a cup of coffee.

TwiddlerWriter is meant to be a simple text entering app where you write only your raw text and copy&paste the text to actual app you will be using your text.

With 'Copy Text' button you can copy the whole text to clipboard.
'Read All' button reads aloud the whole text.
In 'Settings' you can change the pitch and other properties of voice and what are read: only keys, only words or both.

Because app is written with a simple framework you can only write to end of textbox. If you move the cursor to somewhere else than the end of text it will not read the text properly.

The app does not require you to have a Twiddler keyboard. You can of course use app with any kind of keyboard but with a wireless keyboard using this app makes sense.

The app uses no network. Therefore you might need to install first some other app that uses Google Text-to-speech and installs it. I chose the "no network" road that you might feel more safe with app. No ads.

TwiddlerWriter

Thursday, April 16, 2015

Changing Oracle partitioned table to using interval feature

Oracle 11g has new feature to allows for automatic creation of new partitions. It's easy to create table that for instance has automatic range partitions for every month. But how can you change already partitioned table to using interval partitions?

First of all, you cannot have partition that is the 'last' partition meaning it's high_value is MAX_VALUE. You have to delete that partition somehow.There are some methods for doing that but I'll go for easy one.

The examples I have copied from
Rittman Mead.com:Investigating Oracle 11g interval partitioning
I'll explain later why.

First create normally partitioned table
CREATE TABLE INTERVAL_SALES
      ( prod_id        NUMBER(6)
      , cust_id        NUMBER
      , time_id        DATE
      , channel_id     CHAR(1)
     , promo_id       NUMBER(6)
     , quantity_sold  NUMBER(3)
     , amount_sold    NUMBER(10,2)
     )
   PARTITION BY RANGE (time_id)
      ( PARTITION p0 VALUES LESS THAN (TO_DATE('01-01-2005', 'DD-MM-YYYY')),
        PARTITION p1 VALUES LESS THAN (TO_DATE('01-01-2006', 'DD-MM-YYYY')),
        PARTITION p3 VALUES LESS THAN (TO_DATE('01-01-2007', 'DD-MM-YYYY')),
        PARTITION p4 VALUES LESS THAN (MAXVALUE)
        );

-- add some old data
insert into interval_sales values (1,2,to_date('20041201', 'YYYYMMDD'),'d',3,4,9.9);
insert into interval_sales values (1,2,to_date('20051201', 'YYYYMMDD'),'d',3,4,9.9);
insert into interval_sales values (1,2,to_date('20061201', 'YYYYMMDD'),'d',3,4,9.9);
insert into interval_sales values (1,2,to_date('20070101', 'YYYYMMDD'),'d',3,4,9.9);
commit;

-- Show how rows are distributed in partitions
analyze table INTERVAL_SALES compute statistics;
SELECT
   PARTITION_NAME "NAME",
   PARTITION_POSITION "POSITION",
   NUM_ROWS,
   HIGH_VALUE
FROM
   USER_TAB_PARTITIONS
WHERE
   TABLE_NAME in ('INTERVAL_SALES')
ORDER BY
   PARTITION_POSITION;


NAME     POSITION   NUM_ROWS HIGH_VALUE
------ ---------- ---------- --------------------------------------------------------------------------------
P0              1          1 TO_DATE(' 2005-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
P1              2          1 TO_DATE(' 2006-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
P3              3          1 TO_DATE(' 2007-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
P4              4          1 MAXVALUE



We cannot drop the last partition because it already contains data.

So we split the partition. It's best to split to partition sizes that you are going to use in interval.

alter table interval_sales
split partition P4
at ( to_date( '20070201', 'YYYYMMDD' ) )
into ( partition PART200701, partition PART_LAST ) update global indexes;


If you have already a lot of data, this may take some time....

Analyze table and query partition data:

NAME         POSITION   NUM_ROWS HIGH_VALUE
---------- ---------- ---------- --------------------------------------------------------------------------------
P0                  1          1 TO_DATE(' 2005-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
P1                  2          1 TO_DATE(' 2006-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
P3                  3          1 TO_DATE(' 2007-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
PART200701          4          1 TO_DATE(' 2007-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
PART_LAST           5          0 MAXVALUE


If you still have data in last partition , split some more.
But like I said, this is not the fastest method. Every split has to read&write all rows in partition.

But the last partition is now empty, so we can drop it.
alter table interval_sales drop partition part_last update global indexes;

Now we can change the table to interval partioning:
alter table interval_sales set INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'));

Now we add some new data :
insert into interval_sales values (1,2,to_date('20071201', 'YYYYMMDD'),'d',3,4,9.9);
commit;


NAME         POSITION   NUM_ROWS HIGH_VALUE
---------- ---------- ---------- --------------------------------------------------------------------------------
P0                  1          1 TO_DATE(' 2005-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
P1                  2          1 TO_DATE(' 2006-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
P3                  3          1 TO_DATE(' 2007-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
PART200701          4          1 TO_DATE(' 2007-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P221            5          1 TO_DATE(' 2008-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA


It has made a new partition for December 2007!

Now we add some more data to 2007:
insert into interval_sales values (1,2,to_date('20070801', 'YYYYMMDD'),'d',3,4,9.9);
commit;


NAME         POSITION   NUM_ROWS HIGH_VALUE
---------- ---------- ---------- --------------------------------------------------------------------------------
P0                  1          1 TO_DATE(' 2005-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
P1                  2          1 TO_DATE(' 2006-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
P3                  3          1 TO_DATE(' 2007-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
PART200701          4          1 TO_DATE(' 2007-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P241            5          1 TO_DATE(' 2007-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P221            6          1 TO_DATE(' 2008-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA


Because the interval is one month, it has created new monthly partition also for new row.

But this was the problem I started thinking when I read Rittman Mead's blog post. What happens when you add new rows to old yearly partitions? The old yearly partitions have data inside that spans over whole year. Does the interval feature also create new monthly partition to old data? If it does, does it also move data from old yearly partition to new monthly partition? Lots of questions so let's try!

insert into interval_sales values (1,2,to_date('20060712', 'YYYYMMDD'),'d',3,4,9.9);
commit;


NAME         POSITION   NUM_ROWS HIGH_VALUE
---------- ---------- ---------- --------------------------------------------------------------------------------
P0                  1          1 TO_DATE(' 2005-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
P1                  2          1 TO_DATE(' 2006-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
P3                  3          1 TO_DATE(' 2007-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
PART200701          4          1 TO_DATE(' 2007-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P241            5          1 TO_DATE(' 2007-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P221            6          1 TO_DATE(' 2008-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA


No, it does not create new partition. Ok. How does it know which partition was created manually and which with monthly interval? There's a new column 'interval' for table user_tab_partitions.

SELECT
   PARTITION_NAME "NAME",
   PARTITION_POSITION "POSITION",
   INTERVAL
FROM
   DBA_TAB_PARTITIONS
WHERE
   TABLE_NAME in ('INTERVAL_SALES')
ORDER BY
   TABLE_NAME, PARTITION_POSITION;
 

NAME   POSITION INTERVAL
---------- -------------- --------------
P0                           1 NO
P1                           2 NO
P3                           3 NO
PART200701          4 NO
SYS_P241              5 YES
SYS_P221              6 YES


So when partitioning is set to interval, it only splits new interval partitions, not the old manually created ones. 

Ok, let's get difficult.

insert into interval_sales values (1,2,to_date('20071224', 'YYYYMMDD'),'d',3,4,9.9);
commit;

Now we have to rows at December 2007, one in 1st day and one in 24th.

Now we change the partition interval to days:
alter table interval_sales set INTERVAL(NUMTODSINTERVAL(1, 'day')) ;

And add new row to 15th day:
insert into interval_sales values (1,2,to_date('20071215', 'YYYYMMDD'),'d',3,4,9.9);
commit;



NAME         POSITION   NUM_ROWS HIGH_VALUE
---------- ---------- ---------- --------------------------------------------------------------------------------
P0                  1          1 TO_DATE(' 2005-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
P1                  2          1 TO_DATE(' 2006-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
P3                  3          2 TO_DATE(' 2007-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
PART200701          4          1 TO_DATE(' 2007-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P241            5          1 TO_DATE(' 2007-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P221            6          3 TO_DATE(' 2008-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA


So it does not split it to daily partitions. Why not?
Because when we ran alter table interval, Oracle changes every partition to manually created:

NAME  POSITION INTERVAL
---------- ------------- ---
P0                         1 NO
P1                         2 NO
P3                         3 NO
PART200701        4 NO
SYS_P241            5 NO
SYS_P221            6 NO



I'm out of tricks, Oracle has thought of everything :)