sobota 14. května 2016

dash cam to timelapse

My dash cam produces AVI video file every 5 minutes. I decided to create timelapse from the videos on linux using ffmpeg. Following the inspiration
I created following script

for f in *.AVI; do echo "file $f" >> files.txt; done 

[a file called "files.txt" is created] 

#create scaled timelapse 
ffmpeg -f concat -i files.txt -an -vcodec libx264 -filter:v 'setpts=0.05*PTS,scale=640:480' dashcam.mov

Happlink (formerly Plug-Up) Security KEY on Fedora 23

After several hours I managd to get Plug-Up SecureKEY U2F token working on Fedora 23. Some Ubuntu ubased advisory recommends to add an udev rule in a form of [not working]:

SUBSYSTEM=="usb", ATTRS{idVendor}=="2581", ATTRS{idProduct}=="f1d0", MODE="0660", GROUP="[the right  group user is member of]"  

After many minutes of google-fu I managed to get it working. The magic spell is this:

# Happlink (formerly Plug-Up) Security KEY
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2581", ATTRS{idProduct}=="f1d0", TAG+="uaccess"


and the spell should be written into /etc/udev/rules.d/10-sec-key.rules

then run udevadm trigger


Sources:

http://www.ha-obsession.net/2016/04/fedora-23-kde-using-gpg-yubikey4-pcscd.html

http://askubuntu.com/questions/674064/happlink-plug-up-fido-u2f-security-key-why-it-doesnt-work-immediately-in-ubuntu


neděle 29. listopadu 2015

Print images on POS printer

For some unimportant reason I have mini thermal bluetooth printer IMP006A (ordered from alibaba.com). It is reliable piece of HW which I spent some time playing with.

Here you can see the result. Except receipts the printer can be used to print images. Here I share the piece of java code that does the magic.

The image to be printed must be in PBM format max. 373 px width. During the printing process the image is rotated 90 degrees clockwise.

You can use ImageMagick convert utility to prepare the image for printing.

convert  saturn.png \
        -rotate -90 \
        -scale x373  \
        -dither FloydSteinberg \
        -colors 2 \
         image.pbm

Where saturn.png is the input image of any kind ImageMagick can read. 
image.pbm is the resulting pbm image ready to be printed. 

The image is 
  • saturn.png - read from a file
  • -rotate -90 - rotated 90 degrees CCW
  • -scale x373 - scaled to full width of paper
  • - dither ... -colors 2 - color are reduced to 2 (BW) using dithering to render shades of gray on BW device
  • image.pbm - converson result is written to a file
Then if you have the code compiled just run:

java  printqr.PrintQR  image.pbm

And you will get image.prn containg a set of commands for the printer to print the image. Use linux command line to send the data to the printer.

Use USB to connect the printer to Linux box. When connected to linux box with recent distro (tested on Fedora 20), the printer will be accessible as /dev/usb/lp0. By default the device is accessible for root (and lp group members) only. Send the data to the printer usinf gollowing command:

sudo sh -c 'cat image.prn > /dev/usb.lp0'

And that's all. 

For illustration (click to enlarge):



Code:


package printqr;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;

/** Maximum image printed width (input height - the image is rotated) should be 373 px
  *
  * To prepare image for printing:
  * convert saturn.png  -rotate -90 -scale x373 -dither FloydSteinberg -colors 2 image.pbm
  *  or
  * convert saturn.png   -rotate -90 -scale x373 -dither Riemersma -colors 2 image.pbm
  *
  *
 * */

public class PrintQR {
    final static int[] wsChars=new int[] {' ','\n','\t'};
   
    public static void main(String[] args){
        FileInputStream fis=null;
        FileOutputStream fos=null;
        try {
           
            //prepare image name
            String inputImage="image.pbm";
            if (args.length>0)
                inputImage=args[0];
           
            if (! inputImage.endsWith(".pbm"))
                throw new IllegalArgumentException("Input image must be NetBPM PBM format with .pbm extension.");
           
            //open and read image
            fis=new FileInputStream(inputImage);
            //read header
            expectChar(fis,'P');           
            expectChar(fis,'4');
            expectWhitespace(fis);
            int width=readDecimal(fis);
            int height=readDecimal(fis);
           
            //read data
            int rowWidthBytes= width%8 == 0 ? width / 8 : width / 8 +1 ;
            int dataLength=rowWidthBytes*height;
            byte[] data=new byte[dataLength];
            int off=0;
            int remaining=dataLength;
            while (remaining>0){
                int cnt=fis.read(data, off, remaining);
                remaining-=cnt;
                off+=cnt;
            }
           
            System.out.printf("Loaded image %d x %d\n", width, height);
           
            fos=new FileOutputStream(inputImage.replace(".pbm", ".prn"));
           
            //reset printer
            fos.write(new byte[]{0x1b,0x40});
           
            //set linespacing 0
            fos.write(new byte[]{0x1b,0x33,0x00});
           
            //print image
            printBitmap24pinDoubleDensity(width, height, data, fos);
           
        }
        catch (Exception e){
            e.printStackTrace();
        }
        finally {
            if (fos!=null) try {fos.close();}catch (Exception e){};
            if (fis!=null) try {fos.close();}catch (Exception e){};
        }
    }

    /**
     * Sends image to the printer in the right format with the right commands
     * @param width
     * @param height
     * @param data
     * @param fos
     * @throws IOException
     */
    private static void printBitmap24pinDoubleDensity(int width, int height, byte[] data,
            FileOutputStream fos) throws IOException {
        int bWidth=width%8 == 0 ? width / 8 : width / 8 +1;
        int hLow=(height) & 0x000000ff;
        int hHigh= ( (height) >> 8 )& 0x000000ff;
       
        for (int x=0; x< bWidth; x+=3){
            // ESC * m nL nH d1... dk
            // m - 0x21 for 24 pin printer double density
            // nL/nH - low/high byte of number of "strokes", each stroke consists of 24 dots (8 bytes)
            // data should be (nL+nH*256)*3 bytes
            fos.write(new byte[]{0x1b,0x2a,0x21,(byte)hLow,(byte)hHigh});
           
            //get appropriate data from image - for the operation concider image rotated 90 deg CCW
            for (int y=height-1; y>=0; y--){
                fos.write(new byte[]{
                        get(data,x,y,bWidth, height),
                        get(data,x+1,y,bWidth, height),
                        get(data,x+2,y,bWidth, height),
                });
            }
            fos.write('\n');
        }
    }
   
    /**
     * Extracts byte of image data - the image is like this in mempory 
     *  ----------------X----------------------->
     * |          0        1        2        3        4        5
     * | 0 ........ ........ ........ ........ ........ ........
     * | 1 ........ ........ ........ ........ ........ ........
     * | 2 ........ ........ .####### ######## ........ ........
     * Y 3 ........ ........ .####### ####.... ........ ........
     * | 4 ........ ........ .######. ........ ........ ........
     * | 5 ........ ........ .#...... ........ ........ ........
     * | 6 ........ ........ .#...... ........ ........ ........
     * V 7 #.#.#.#. .#.#.#.# ....#... ........ ........ ........
     *
     * First triplet sent to printer is
     * this [0,7],[1,7],[2,7]
     * then [0,6],[1,6],[2,6]
     * then [0,5],[1,5],[2,5]
     * and so on
     *
     * This effectively rotates image CCW 90 deg.   
     *
     * @param data
     * @param x
     * @param y
     * @param bWidth
     * @param height
     * @return
     */
    public static byte get(byte[] data, int x, int y, int bWidth, int height){
        if( x>= bWidth ) return 0; //handle request beyond image for images not %24 print height
        int idx=y*bWidth+x;
        if (idx<0 || idx>=data.length)
            return 0;
        return data[idx];
    }
   
    public static int expectChar(InputStream is, int expectedChar)
        throws IOException
    {
        int readChar=is.read();
        if (readChar==expectedChar) return readChar;
       
        throw
            new IllegalStateException(String.format("Expected %c found %c",expectedChar, readChar));
    }
   
    public static int expectWhitespace(InputStream is)
            throws IOException
    {
        int readChar=is.read();
        if (isWhitespace(readChar)) return readChar;
        throw
            new IllegalStateException(String.format("Expected whitecpace found %c",readChar));
    }
   
    public static int readDecimal(InputStream is)
        throws IOException
    {
        int accumulator=0;
        while (true){
            int c=is.read();
            if (isWhitespace(c)) return accumulator;
            else
                if (c>='0' && c<='9') accumulator=accumulator*10+(c-'0');
                else
                    throw
                        new IllegalStateException(String.format("Expected digit or whitecpace found %c",c));
        }       
    }
   
    public static boolean isWhitespace(int c){
        for (int i=0; i<wsChars.length; i++){
            if (c==wsChars[i]) return true;
        }
        return false;
    }


    /** not tested */
    private static void printBitmap9pin(int width, int height, byte[] data,
            FileOutputStream fos) throws IOException {
        int bWidth=width%8 == 0 ? width / 8 : width / 8 +1;
        int hLow=height & 0x000000ff;
        int hHigh= ( height >> 8 )& 0x000000ff;
       
        for (int x=0; x< bWidth; x++){
            fos.write(new byte[]{0x1b,0x2a,0x00,(byte)hLow,(byte)hHigh});
            for (int y=height-1; y>=0; y--){
                fos.write(get(data,x,y,bWidth, height));
            }
            fos.write('\n');
        }
    }

    /** not tested */
    private static void printBitmap9pinDoubleDensity(int width, int height, byte[] data,
            FileOutputStream fos) throws IOException {
        int bWidth=width%8 == 0 ? width / 8 : width / 8 +1;
        int hLow=height & 0x000000ff;
        int hHigh= ( height >> 8 )& 0x000000ff;
       
        for (int x=0; x< bWidth; x++){
            fos.write(new byte[]{0x1b,0x2a,0x01,(byte)hLow,(byte)hHigh});
            for (int y=height-1; y>=0; y--){
                fos.write(get(data,x,y,bWidth, height));
            }
            fos.write('\n');
        }
    }
}








Licence Creative Commons
Graphical printing tool for POS printer, jehož autorem je LRA, podléhá licenci Creative Commons Uveďte původ-Zachovejte licenci 4.0 Mezinárodní .

čtvrtek 26. února 2015

.. on a trip to the C world again

Testing lua embedding and mongoose http server.
Lua is great to implement business logic in the C based app.
It lets you bee less woried about memory leaks, stack overruns, invalid pointer etc.

úterý 24. února 2015

online collaboration in realtime

Some projects for online collaboration:
http://etherpad.org/ - realtime colaboration for text editing
http://socket.io/  - bidirectional realtime communication platform
http://XMPP.org - realtime presence & message protocol

středa 18. února 2015

Tune SSL on Apache 2.4/Windows

Today I spent some time to tune Apache SSL settings to be Grade A at https://www.ssllabs.com/ssltest/.
Finding the equilibrium point between compatibility and transport security took some time. To save yours, I'm sharing the final configuration here.

Some notes at first. I favored security over backward compatibility and so some older (very old in fact) browsers will fail to establish connection. I tried to cope with all failed tests, but not succseeded. There stil are some Failed tests. Those tests are not affecting the main purpose of the server.

  1. Download and install the latest Apache 2.4 binaries to overcome known CVE
  2. I'm using http://www.startssl.com/ as the server certification authority.
  3. Tune SSL Protocol and Ciphersuites and some others at a server level (httpd.conf)
    1. SSLProtocol all -SSLv2 -SSLv3
    2. SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"
    3. SSLHonorCipherOrder on
    4. SSLUseStapling On
    5. SSLStaplingCache shmcb:logs/ssl_stapling(32768)
  4. Add HTTP Strict Transport Security
    1. Enable headers module: 
      1. LoadModule headers_module modules/mod_headers.so
         
    2. Set header to require HSTS at the VirtualHost level
      1. Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
And you are done.


pátek 13. února 2015

... DIY electronics

From time to time I learn about new DIY electronic project. Here I will sumarize all of them in a short notice:

littleBits

Creations are constructed by placing bits&pieces together glued by magnetic force and connected by contacts. Cloud enabled.
SmartHome Kit - $249 per 14 modules -  $17/module.

SAM

Standalone bits equiped with bluetooth low energy connectivity connected by SW configuration. Battery in a module lasts from 3 weeks of operation (button) to 1 hour (motor). MicroUSB charger.
Cloud enabled.
SAM Pro  - GBP 349 per 11 modules -  GBP31/module



úterý 13. ledna 2015

... backup with Areca

I'm giving try to Areca backup tool which seems as a good multiplatform (Java) tool for simple backup tasks on a workstation and small server.
It is featuring pretty usable GUI and command line interface for common backup tasks.



pondělí 6. října 2014

... and another Apache httpd story ... client authentication of proxied requests

Centos/RHEL 6.3, apache httpd 2.2.15
The goal is - let te httpd listens at port 80 plain unencrypted HTTP requests. The request will be forwared  to https://some.site/ where there is a HTTPS with client authentication.

Findings:

Client certificate key/cert file format (directive SSLProxyMachineCertificateFile):
  • key + certificate need to be in single PEM file looking something like
    -----BEGIN RSA PRIVATE KEY-----
    MIIE...
    ...
    ...
    ...
    -----END RSA PRIVATE KEY-----
    -----BEGIN CERTIFICATE-----
    MII...

    ...
    .,
    ...
    -----END CERTIFICATE-----
  • mind the RSA part (emphasized above)  of private key header - some openssl versions use the header with and some without the RSA letters
  • without RSA
  • my version of apache httpd wants it there
Re-negotioation at the server side is not supported. The server should be configured to protect every request with client auth. To avoid TLS renegotiation when entering protected resource, SSLClientVerify should be configured at VirtualHost level or server level.

After above changes were made server started and operated as expected.

References:
http://apache-http-server.18135.x6.nabble.com/Apache-fails-to-start-if-SSLProxyMachineCertificateFile-does-not-contain-RSA-td5009238.html


pondělí 29. září 2014

Apache httpd 2.4.6 hangs not servicing HTTPS

A lot of pain ... till solution found
# Apparently this fixes an issue with Apache 2.4.6 on Windows hanging
# when serving requests from Internet Explorer 10/11.
# see http://stijndewitt.wordpress.com/2014/01/10/apache-hangs-ie11/
AcceptFilter http none
AcceptFilter https none



neděle 7. září 2014

... Google Authenticator or Doogee DG800 strange error

After purchasing new chinese Android phone I needed to install Google Authenticator. But had no luck. The application worked fine but ... generated codes did not work. I tried other phones and came to a strange conclusion. The other Doogee DG800 I had show she same codes. Bud all other Android phones shown different codes. For sure all the phones shared the same secret.  The strange thing was the codes were different in some digits only. Typical difference looked like this 605678 - 604356.

As the authenticator codes are derived using hash function (RFC 6238 - TOTP), in case of an error there should be completely different results.

Fortunately - authenticator is an open source software. I cloned the repository and built my own version for debugging.

And here is the source of difference. During the computation a piece of a hash value is taken, converted to integer and then divided by a power of 10 and the remainder is the code:

int code =  truncatedHas % (int)Math.pow(10, codeLength);

On the problematic phone the result of power computation was this:
 Math.pow(10, codeLength): 999999,99999999

After cast to integer the result was 999999.

This is the answer - wrong result from system runtime library because the Math.pow function computes doubles which can be not so precise.

It is rare but it happens.

I'm going to  send a patch which does not uses double computation.

UPDATE: Issue was discussed at Stack Overflow. The main cause is a bug in the phone platform library.

úterý 26. srpna 2014

... firefox 30+ disabled NTLMv1 over insecure connection

NTLMv1 is known to be insecure but if you need it new setting was introduced:
network.negotiate-auth.allow-insecure-ntlm-v1 - defaults to false and NTLMv1 auth request is silently ignored when sent over HTTP. Set it to true to force NTLMv1authentication prompt.

Disclaimer: NTLMv1 over HTTP is considered insecure - you should know what are you doing

pátek 22. srpna 2014

... nssm - non sucking service manager

Seems really usable - new to me.
Why I like it ... it is able to start any command as a service and has several options for service shutdown (Send Ctrl-C, send WM_CLOSE,kill process)

http://nssm.cc/usage


úterý 20. května 2014

Chrome native messaging on windows

Problem:
When developing extension using native messaging you need to develop so called native messaging host - exe which is registered with chrome and  spawned by chrome when requested by the extension.
Chrome uses pipes to communicate with the host. The pipe is connected to stdin/stdout descriptors in the host process.
There is a drawback on windows - default stdin mode is TEXT. But in this mode once 0x1A is passed through, the C library closes the pipe and the host is terminated because 0x1A id end of file marker.

Solution:
Before reading attempt from the pipe set the mode to binary (defaults to text) using following code snippet:

_setmode( _fileno( stdin ), _O_BINARY )

Reference: http://msdn.microsoft.com/cs-cz/library/tw4k6df8.aspx

čtvrtek 10. dubna 2014

Convert SSH public key to a form for .authorized_hosts

Evary time i need this command it takes me minutes to retrieve the right form from my memory. Let's take a note :)

ssh-keygen -i -f pem -f ~/.ssh/id_rsa.pub

neděle 23. března 2014

Error 'LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt - Solved

No Visual Studio 2012 installed just SP1 of Visual Studio 2010.

Found this (no solution, but direction): http://stackoverflow.com/questions/10888391/error-link-fatal-error-lnk1123-failure-during-conversion-to-coff-file-inval

But it did not help.

Found this(almost solusion): http://social.msdn.microsoft.com/Forums/vstudio/en-US/d10adba0-e082-494a-bb16-2bfc039faa80/vs2012-rc-installation-breaks-vs2010-c-projects?forum=vssetup

It pointed me to the root cause - bad version od cvtres.exe which depends on missing msvcr100_clr0400.dll.

Solution: downloaded http://www.dll-files.com/dllindex/dll-files.shtml?msvcr100_clr0400

I downloaded the right version (32bit) of the file and stored it next to cvtres.exe and BINGO!!! compiling with no error.

Sahme on MS ... and shame on MS problem resolution culture. Searching the root cause is seldom seen. Uninstall/Reinstall is the only advice in most of dicussions.
 

 

neděle 8. září 2013

... chromcast like experience on smart tv

No dongle is needed to experience chromcast on SmartTV. In my case LG brand. The youtube app on the TV sucks. It's slow realllyyy sllooow. It's hard to use using only the tv remote. It's hard to use even using much better smart phone remote.       Now ... it is easy to send the youtube video from smart phone youtube app to she big screed of the smart tv.

Try it if you can!

pondělí 19. srpna 2013

... čajnafoun

... dorazil balík z dx.com obsahující telefon N6300. Cena podle kurzu Paypal 3814Kč ($184.60). Po připočtení služby České pošty v rámci celního řízení (180Kč, ale v balíku toho bylo víc, takže do ceny telefonu promítnuto jen částečně) a vyměřeného cla a DPH je reálná nákupní cena 4780Kč.

Telefon dorazil se dvěma kryty - jeden klasický "tenký" - jen zadní kryt. Druhý je pro "tlustší" variantu s větší baterkou a zkládá se ze zadního krytu a z přiklápěčího krytu displeje.

Telefon dorazil se dvěma bateriemi - jedna 1800mAh pro použití s "tenkým" krytem a druhá 2500mAh pro použití s "tlustším" krytem.

Balení dále obsahuje sluchátka, čínský nabíjecí adaptér, USB kabel a již nalepený screen protector.

UPDATE: Nevýhoda čajnafounu se ukázala díky mé nešikovnosti. A teď se nesmějte, protože to bude smutný příběh. Čajnafoun mi spadl do polevky. Fakt. A konektorem napred. A od te doby ... spise nefunguje, nez funguje. Takze jsem musel rychle hledat nahradu. A našel jsem téměř shodně vybavený trochu menší Gigabyte Aku A1. A při nákupu mi nabídli pojistku proti pohromám za 500Kč příplatek. A protože jsem stejnou pojistku využil nedávno u telefonu dětí, kývnul jsem na ni. V případě pádu do polévky by mi ho opravili za drobnou spoluúčast.

čtvrtek 8. srpna 2013

Installing GlusterFS 3.4 on Fedora 19

I was trying to install GlusterFS on Fedora 19. There were some problems which I describe here.

At first ... disable SeLinux on every Gluster node by changing /etc/selinux/config and set entry SELINUX=disabled

Packages of GlusterFS are part of Fedora 19 repository. Installation is easy.
I used following command:

sudo yum install glusterfs glusterfs-api glusterfs-fuse \
   glusterfs-server glusterfs-geo-replication 

After the packages are installed glusterd service is started. To connect the cluster nodes following command need to be issued:

sudo gluster peer probe the-other-node-ip 

But the command failed:

peer probe: failed: Probe returned with unknown errno 10

After some research using resources mentioned bellow I found the source of the problem (as usually): the firewall. Fedora 19 (and 18 already) includes firewalld.

Thing twice before changing your firewall settings. As I use virtualization and host only networking, I moved my host-only interface to the trusted zone:

sudo firewall-cmd --permanent --zone=trusted --add-interface=p7p1
sudo firewall-cmd --permanent --zone=trusted --change-interface=p7p1
sudo systemctl restart firewalld.service

To verify interface move submit:
 
sudo firewall-cmd --zone=public --list-all
sudo firewall-cmd --zone=trusted --list-all



References:

středa 7. srpna 2013

Psycho v letním kině

Dnešní promítání Psycho v letním kině mělo neopakovatelnou atmosféru. Ve chvílích, kdy film graduje se zvedl vítr přicházející bouřky .... ve scéně s Normanovou matkou ve sklepě se plátno divoce vlnilo ve větru a umocňovalo tak atmosféru filmu. Těsně před koncem plátno poryvům větru neodolalo a padlo. Úplně poslední scény s detailním záběrem do tváře Normana jsme sledovali na stěně domu daleko za původním plátnem a obličej byl tudíž obří .... nádhera.