Showing posts with label python. Show all posts
Showing posts with label python. Show all posts

Wednesday, June 28, 2017

Playing Yeelight with Python

Recently I've been playing a Yeelight Smart LED Bulb. It'd be a good starting of learning home automation, as such smart LED Bulbs do not depend on any modification of your home electricity system. This yeelight bulb is already bundled with the WIFI chip so that you can configure it using its official app (both Android and iOS are available)

Using the official app is straight forward, then I wondered can I play it 'harder'. Then I searched and found some interest use cases:

  1. Controlling yeelight by Python
  2. Controlling yeelight by Siri (wow!)
  3. Controlling yeelight by Home-Assistant
In fact there should be more cases, including Amazon Alexa or Google Home, but I do have these products and the setup will be very similar to 2. and 3, that I will explain it in another post later. Right now I am going to share how to play the yeelight with python.

First, you need the official app to enable developer mode. Then just use python yeelight package https://yeelight.readthedocs.io/en/latest/ and you are good to go!

import yeelight
yeelight_ip='xxx.xxx.xx.xxx' # your yeelight bulb IP
light = yeelight.Bulb(yeelight_ip, effect='smooth')
light.turn_off()
light.turn_on()

# Set it to white
light.set_rgb(255,255,255)
# Set the brightness
light.set_brightness(100)



Not very difficult right? If you have a raspberry Pi you can set some cronjobs in order to turn the light on in the morning as a silent  alarm clock, or place the bulb in your kid's bedroom, then change the brightness from 100% to 1% (then off, of course) in one hour.

If you think it's too dummy to control such a bulb, I agree. That's why there will be some more elegant solutions. Next time I'll show how I setup a virtual HomeKit and ask Siri to control the bulb.

Ref:

Friday, November 06, 2015

Sending Whatsapp Messages from Raspberry Pi

yowsup is the Whatsapp library. It is written in python so we can run even with a Raspberry Pi. After the installation there is a client script that we can send message to other Whatsapp user. 

Reasons to use yowsup:
  1. send messages to mobile device like SMS
  2. the cost is cheap: all we need is just a mobile number ( a number that has not been registered in Whatsapp) and a Raspberry Pi ( I am using Raspberry Pi B2, but any model should be found)
Installation

$ virtualenv2 venv/
New python executable in venv/bin/python2
Also creating executable in venv/bin/python
Installing setuptools, pip, wheel...done.
$ . venv/bin/activate
(venv)$ git clone https://github.com/tgalal/yowsup

Cloning into 'yowsup'...
remote: Counting objects: 6983, done.
remote: Total 6983 (delta 0), reused 0 (delta 0), pack-reused 6983
Receiving objects: 100% (6983/6983), 1.49 MiB | 574.00 KiB/s, done.
Resolving deltas: 100% (4388/4388), done.
Checking connectivity... done.

python setup.py  install

After the setup there will be a script "yowsup-cli"

Registration

Prepare the following information:
    • the phone number           (XXXXXXXX)
    • the country code             (CCC)
    • the mobile country code (mcc)
    • the mobile network code (mnc)

Note that the phone number is in the form of Country Code + Number. And the mcc and mnc can be found at https://en.wikipedia.org/wiki/Mobile_country_code

For example, if you are using Verizon LTE in US, that the mcc and mnc should be 310 and 012 respectively.

Run the command:
./yowsup-cli registration --requestcode sms --phone CCCXXXXXXXX --cc CCC --mcc 310 --mnc 012

INFO:yowsup.common.http.warequest:{"status":"sent","length":6,"method":"sms","retry_after":1805}

status: sent
retry_after: 1805
length: 6
method: sms


If you are lucky enough you will receive a SMS from the mobile phone.

With this WhatsApp code we can run another command:
./yowsup-cli registration --register 800-269 --phone CCCXXXXXXXX --cc CCC
INFO:yowsup.common.http.warequest:{"status":"ok","login":"CCCXXXXXXXX","pw":"kaiaCmXHgRxxxvuOfbbCFHlqbLI=","type":"new","expiration":1478245880,"kind":"free","price":"$1.00","cost":"1.00","currency":"USD","price_expiration":1449782266}

status: ok
kind: free
pw: kaiaCmXHgRxxxvuOfbbCFHlqbLI=
price: $1.00
price_expiration: 1449782266
currency: USD
cost: 1.00
expiration: 1478245880
login: CCCXXXXXXXX
type: new


Note that the line pw: xxxxxxxxxxxxx . That's the password we need to put in a config file.

create a file yowsup-cli.conf with the following content:

cc=CCC # The country code
phone=XXXXXXXX # the phone number
id= # 
password=xxxxxxxxxxx # the password

Finally we can test by sending a message to a Whatsapp user (eg. CCCYYYYYYYY):

./yowsup-cli demos -c yowsup-cli.conf -s YYYYYYY “hello world”


By using the simple command we can send Whatsapp message to another user programmatically. Possible usages are to send alerts when some health check jobs failed, or writing authentication apps that can send the passcode.

Ref:
  • https://github.com/tgalal/yowsup
  • https://en.wikipedia.org/wiki/Mobile_country_code



Friday, October 30, 2015

Using trickle to control the bandwidth usage of a particular process

Recently I have written a little python script to upload my photos to flickr using the flickr api. It was fun and I will share how to do it later. However when I started uploading 600 photos to flickr at home my wife complained the Internet speed was too slow. She said she could not watch youtube and even some foreign website!

Telling her to wait is not a solution ( I could be killed :p ). So I had stop the script and wait for the 'non-busy hour' to continue. However, this way is not practical, because it's hard to define a non-busy hour. In fact, mid night might not be good as well, because sometimes I need to have a conference call. Therefore, I tried to find if any tools that can limit the traffic so that the script will not upset our life.

Finally I found trickle and it totally solves my problem.

First, we have to install trickle.

Depending on the distributions:

  • pacman -S trickle
  • apt-get install trickle
  • yum install trickle

To run a program with limited bandwidth, just run:
$ trickle -s -u UPLOAD -d DOWNWORD THE_PROGRAM

in my case:

$ trickle -s -u 40 -d 40 python flickr_upload.py

-d and -u are to specify the download and upload speed respectively. Remember the unit is KB/s while your ISP usually use kbs as the unit. You will need to convert it in order to set a reasonable throughput for the process. You can check with this online conversion calculator. 

If you have a set of programs run by an user you can limit them buy running a trickled. For example:
$ trickled -u 40 -d 40
$

Then you can limit any program run by this user with this limit setting:
$ trickle program1

$ trickle program2
$ # more...

After limited the upload and download speed of my python script, everybody is satisfied. Though it takes much longer to upload photos to flickr, it's okay for me and my wife can browse and watch whatever she wants. Happy ending...

PS: 
Please note that trickle cannot resolve all cases. It only works when the application (the binary) is using the dynamic library glibc. To check if it is using the glibc, you can use the following command

$ ldd /usr/bin/python |grep libc
libc.so.6 => /usr/lib/libc.so.6 (0x00007f96a991f000)

If it is not using glibc, then you have find another way, probably using iptable or enable QoS on the router if it is supported

Ref:

  1. https://wiki.archlinux.org/index.php/Trickle
  2. http://linux.die.net/man/1/trickle

Monday, February 18, 2013

Setup Trac on Raspberry Pi as a Wiki and Issue Tracking Tool

Trac with GIT

Trac is a wiki and issue tracking tool. There are other choices such as redmind and mantisbt. However, Trac is the most suitable one for running on Raspberry Pi because:
  1. it is run by python, which is installed by default for raspbian. (php and ruby are not required)
  2. it is relatively light weight. It can use sqlite as the database, rather than MySQL or PostgresSQL.
  3. it can be run in standalone mode, without using apache or lighttpd. (although I will still use lighttpd to 'proxy' Trac)
  4. It supports modern version control tool such as Subversion and GIT. (redmine also supports, but again, it's not that light weight)
  5. with making use of virtual environment (virutalenv), you can setup Trac without using a privilege account.
  6. it is a mature product and many organizations are using it (http://trac.edgewall.org/wiki/TracUsers)

Install and setup Trac

First, make sure virtualenv is already installed. (apt-get install virtualenv)

Thursday, November 22, 2012

Create a Wiki (Moinmoin) on Raspberry

Moinmoin is a very good Wiki application without using a DB. It is very fast, with easy syntax and I recommend to use it as a quick knowledge base for home or SME usage.

 This guide is to install moinmoin on a Raspberry Pi and make it accessible via Lighttpd (using fastcgi). It is assumed a virtual host is available for this wiki (eg. http://wiki.example.com )
The moinmoin program will be installed at /usr/local/moinmoin_engine while the instance will be installed at another place (eg. /usr/local/moinmoin_instance1. )
  1. Download the latest source (1.9.5 as of this moment) at http://moinmo.in
  2. extract the tar ball to a temp place (eg. /tmp)
  3. under the source path, run
    python setup.py install --prefix=/usr/local/moinmoin_engine
  4. mkdir the instance path
    mkdir /usr/local/moinmoin_instance1
  5. copy the following directories from "engine" to "instance", and change the ownership to the lighttpd user:
    cp -r /usr/local/moinmoin_engine/share/moin/data /usr/local/moinmoin_instance1
    cp -r /usr/local/moinmoin_engine/share/moin/underlay /usr/local/moinmoin_instance1
    cp /usr/local/moinmoin_engine/share/moin/config/wikiconfig.py /usr/local/moinmoin_instance1
    cp /usr/local/moinmoin_engine/share/moin/server/moin.fcgi /usr/local/moinmoin_instance1
    chown -R www-data:www-data /usr/local/moinmoin_instance1
  6. modify the moin.fcgi, locate the following lines:
    # a1) Path of the directory where the MoinMoin code package is located.
    #     Needed if you installed with --prefix=PREFIX or you didn't use setup.py.
    #sys.path.insert(0, 'PREFIX/lib/python2.3/site-packages')
    sys.path.insert(0, '/usr/local/moinmoin_engine/lib/python2.7/site-packages')
    
    # a2) Path of the directory where wikiconfig.py / farmconfig.py is located.
    #     See wiki/config/... for some sample config files.
    #sys.path.insert(0, '/path/to/wikiconfigdir')
    sys.path.insert(0, '/usr/local/moinmoin_instance1')
    
    ...
    
    ## this works around a bug in flup's CGI autodetection (as of flup 1.0.1):
    #os.environ['FCGI_FORCE_CGI'] = 'Y' # 'Y' for (slow) CGI, 'N' for FCGI
    os.environ['FCGI_FORCE_CGI'] = 'N'
    
    ...
    
    # Is fixing the script name needed?
    # Use None if your url looks like http://domain/wiki/moin.fcgi
    # Use '' if you use rewriting to run at http://domain/
    # Use '/mywiki' if you use rewriting to run at http://domain/mywiki/
    #fix_script_name = None  # <-- adapt="adapt" as="as" class="anchor" here="here" id="line-24" needed="needed" span="span">
fix_script_name = ''# <-- adapt="adapt" as="as" here="here" needed="needed" pre="pre">
  • Next prepare virtual host by appending the following block /etc/lighttpd/lighttpd.conf:
    $HTTP["host"] =~ "wiki\.example\.com" {
            
      fastcgi.server += ( "/" =>
          ((
            "socket" => "/tmp/moin.socket",
            "min-procs" => 1,
            "max-procs" => 2,
            "check-local" => "disable",
            "bin-path" => "/usr/local/moinmoin_instance1/moin.fcgi",
            "fix-root-scriptname" => "enable"
          ))
      )
    
      alias.url += ( "/moin_static195" => "/usr/local/moinmoin_engine/lib/python2.7/site-packages/MoinMoin/web/static/htdocs")
    
    }
  • Restart Lighttpd and the your own wiki is just born! 

  • For more information about user and administration guide, please refer the HelpContents.

    PS: So here is the wiki running on my Raspberry Pi: http://wiki.jessed121.us/ . You can walk around and feel it.

    Install Lighttpd, PHP5, MySQL on Raspberry Pi

    To run a 'typical' server on Raspberry Pi, a Web server is necessary. If possible, it can run application (by PHP5, Java, Perl, Python, etc...). Apache may be the most famous web server, but here I choose Lighttpd is it is not as big as Apache. In fact, a lightweight server is more suitable. Also, it will use FastCGI to run PHP and Python, I will list out what applications/ services to be run on this server.

    Finally Mysql is also a popular DB. At the beginning I don't want to install it as there may be a huge overhead on the Pi. In fact, some embedded DB such as sqlite would be a better option. However, there are still applications which only official support Mysql, so at last I decide to install it and hopefully can fine-tune it later.

    So here is the steps...

    Install Lighttpd and PHP5

    1. Login as root
    2. create the user and group "www-data"
    3. Install the following packages:
      • apt-get update (get the latest repository)
      • apt-get install lighttpd php5-cgi
    After installation, check the /etc/lighttpd/lighttpd.conf
    include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
    it will includes setting under /etc/lighttpd/conf-enabled. Make sure there is something like "fastcgi" and "fastcgi-php". (The settings can be fine tuned afterwards)
    # ls /etc/lighttpd/conf-enabled/
    10-fastcgi.conf  15-fastcgi-php.conf

    Install Mysql

    just install the packages "mysql-server", "php5-mysql"

    Tuesday, November 20, 2012

    Weather information from openweathermap.org JSON API by Python

    The openweathermap.org offers JSON API to query weather information around the world. It is not difficult to use python to call the API, parse the JSON and gather the information.

    Since all the request are from web, it'd better to prepare a simple function to fetch the HTML/JSON from the site:

    import urllib2, json

    def fetchHTML(url):
        req = urllib2.Request(url)
        response=urllib2.urlopen(req)
        return response.read()

       
    Remember it is just for a quick and dirty approach. In real case we should handle exceptions (such as URL unreachable, network not found, etc)

    Now we are ready to call the API. First of all we need to know the "id" of a City. http://openweathermap.org/data/2.1/find/name?q=<CITY>