<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://mehmandarov.com/tag/python/feed.xml" rel="self" type="application/atom+xml"/><link href="https://mehmandarov.com/tag/python/" rel="alternate" type="text/html"/><updated>2017-03-11T12:06:00+01:00</updated><id>https://mehmandarov.com/tag/python/feed.xml</id><title type="html">Rustam Mehmandarov - tag: python</title><subtitle type="text">Posts tagged &quot;python&quot; on Rustam Mehmandarov.</subtitle><author><name>Rustam Mehmandarov</name></author><entry><title type="html">Micro:bit Bluetooth Challenge</title><link href="https://mehmandarov.com/microbit-bluetooth-challenge/" rel="alternate" type="text/html" title="Micro:bit Bluetooth Challenge"/><published>2017-03-11T12:06:00+01:00</published><updated>2017-03-11T12:06:00+01:00</updated><id>https://mehmandarov.com/microbit-bluetooth-challenge</id><content type="html" xml:base="https://mehmandarov.com/microbit-bluetooth-challenge/"><![CDATA[<p><em>Can you build Scissor-Paper-Rock game using micro:bit and Bluetooth?</em></p>

<ul>
  <li><a href="#the-challenge">The Challenge</a></li>
  <li><a href="#the-building-blocks">The Building Blocks</a></li>
  <li><a href="#extra">Extra</a></li>
</ul>

<hr />

<p>This post is the challenge for the Race Condition badge at <a href="http://ariot.no/Home/Badges" target="_blank">Arctic IoT Challenge</a>. The description for the badge is as follows:</p>

<blockquote>
  <p>At random, the jury will present a challenge. Timeboxed to one hour, the first team with a working solution gets all the points.</p>
</blockquote>

<p>This time I am designing the challenge, so here it comes:</p>

<hr />

<h2 id="the-challenge">The Challenge</h2>

<p>We want you to simulate a popular Scissor-Paper-Rock game using <a href="https://en.wikipedia.org/wiki/Micro_Bit" target="_blank">micro:bits</a>. Each team gets two devices.</p>

<ul>
  <li>On shake the micro:bit should pick a random shape (scissors, paper, or rock) and show it using LED array on the device</li>
  <li>The two devices should connect and send the data over to each other</li>
  <li>The opposite device compares then its shape to the one received and decides whether it won or lost</li>
  <li>Each of the two micro:bits shows then &#8220;Won&#8221; or &#8220;Lost&#8221; on the LED array.</li>
</ul>

<hr />

<h2 id="the-building-blocks">The Building Blocks</h2>

<h3 id="connecting-to-a-microbit">Connecting to a micro:bit</h3>
<p>Connect the micro:bit to your computer using a micro USB cable. It should appear as a USB disk on your machine.</p>

<h3 id="editor-and-language">Editor and Language</h3>
<p>Yan can use Python and the editor here: <a href="http://python.microbit.org/editor.html" target="_blank">http://python.microbit.org/editor.html</a>.</p>

<p>After you are done writing the code, click <em>Download</em>, and you will get a binary file you will be using in the next step. Check out the <a href="http://python.microbit.org/help.html" target="_blank">help section</a> for more information.</p>

<p>Python documentation for the API can be found <a href="https://microbit-micropython.readthedocs.io/en/latest/index.html" target="_blank">here</a>.</p>

<h3 id="deploying-to-a-microbit">Deploying to a micro:bit</h3>
<p>Copy the binary *.hex file from the previous step on to the micro:bit, just like you would copy to any USB drive.</p>

<h3 id="sending-data-between-microbits">Sending Data Between micro:bits</h3>
<p>Now, over to connecting micro:bits and sending data over. Take a look at the example below. Make sure to change <em>group=1</em> to a number between 0 and 255. Both chips should belong to the same group to connect with each other. You will be assigned a number.</p>

<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="n">microbit</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="n">radio</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="n">random</span> <span class="kn">import</span><span class="o">*</span>

<span class="c1">#turn radio on and configure group
</span><span class="nf">on</span><span class="p">()</span>
<span class="nf">config</span><span class="p">(</span><span class="n">group</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">length</span><span class="o">=</span><span class="mi">251</span><span class="p">)</span>

<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">button_a</span><span class="p">.</span><span class="nf">was_pressed</span><span class="p">():</span>
        <span class="c1">#send the images
</span>        <span class="nf">send</span><span class="p">(</span><span class="sh">"</span><span class="s">Hello, World!</span><span class="sh">"</span><span class="p">)</span>
     
    <span class="c1">#receive data    
</span>    <span class="n">data</span> <span class="o">=</span> <span class="nf">receive</span><span class="p">()</span>
    
    <span class="c1">#check that we have received any data
</span>    <span class="k">if</span> <span class="n">data</span> <span class="o">!=</span> <span class="bp">None</span><span class="p">:</span>
        
        <span class="c1">#split the data into different pictures by the marker
</span>        <span class="n">display</span><span class="p">.</span><span class="nf">scroll</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>

        <span class="c1">#clear the screen
</span>        <span class="n">display</span><span class="p">.</span><span class="nf">clear</span><span class="p">()</span></code></pre></figure>

<h3 id="the-scissor-paper-rock-game">The Scissor-Paper-Rock Game</h3>
<p>Have a look at the <a href="https://www.microbit.co.uk/blocks/lessons/rock-paper-scissors/challenges" target="_blank">simple implementation of the game</a>. You will need to translate it to MicroPython and extend.</p>

<p><img src="/assets/images/posts-images/2017-03-11-microbit-bluetooth-challenge-1.jpg" alt="Pseudocode for the Scissor-Paper-Rock Game" /></p>

<hr />

<h2 id="extra">Extra</h2>
<p><em>[Spoiler alert!]</em> The winning team gets to submit their code to this <a href="https://github.com/mehmandarov/scissor-paper-rock-microbit" target="_blank">GitHub repo</a>.</p>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">Scissor-Paper-Rock challenge using micro:bit and Bluetooth</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/clouds.jpg"/><category term="blog"/><category term="iot"/><category term="python"/><category term="english"/><category term="conferences"/></entry><entry><title type="html">Automating Confluence Posts with Amazon Cloud (AWS)</title><link href="https://mehmandarov.com/confluence-and-aws/" rel="alternate" type="text/html" title="Automating Confluence Posts with Amazon Cloud (AWS)"/><published>2017-01-29T09:26:00+01:00</published><updated>2017-01-29T09:26:00+01:00</updated><id>https://mehmandarov.com/confluence-and-aws</id><content type="html" xml:base="https://mehmandarov.com/confluence-and-aws/"><![CDATA[<p><em>How do you automate a job without setting up a dedicated machine?</em></p>

<ul>
  <li><a href="#posting-via-confluence-rest-api">Posting via Confluence REST API</a></li>
  <li><a href="#creating-a-lambda-function-in-aws">Creating a Lambda Function in AWS</a></li>
  <li><a href="#schedule-it">Schedule it!</a></li>
</ul>

<hr />

<p>Some mundane tasks can easily be automated. In my case, I needed something that could post to our Confluence instance at a specific time every week. This is because we use blog posts in Confluence for announcing our weekly volunteer meetings and as a simple attendance management.</p>

<hr />

<h2 id="posting-via-confluence-rest-api">Posting via Confluence REST API</h2>

<p><a href="https://en.wikipedia.org/wiki/Confluence_(software)" target="_blank">Confluence</a>, a team collaboration software written in Java and quite often used in corporate environments, offers a <a href="https://developer.atlassian.com/confdev/confluence-server-rest-api/confluence-rest-api-examples" target="_blank">REST API</a> that makes it possible to perform many operations on the content. In this case, I was interested in posting new content with some text, and I was getting tired of doing that manually every week. So, I thought: <a href="https://xkcd.com/1319/" target="_blank">&#8220;I spend a lot of time on this task. I should write a program automating it!&#8221;</a>.</p>

<p>The first take on that problem was a simple Python script:</p>

<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="n">json</span>
<span class="kn">import</span> <span class="n">requests</span>

<span class="n">url</span> <span class="o">=</span> <span class="sh">"</span><span class="s">https://some-confluence-url.com/rest/api/content/</span><span class="sh">"</span>
<span class="n">headers</span> <span class="o">=</span> <span class="p">{</span> <span class="sh">"</span><span class="s">content-type</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">application/json</span><span class="sh">"</span> <span class="p">}</span>
<span class="n">payload</span> <span class="o">=</span> <span class="p">{</span> <span class="sh">"</span><span class="s">type</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">blogpost</span><span class="sh">"</span><span class="p">,</span>
            <span class="sh">"</span><span class="s">title</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">Fancy meeting title</span><span class="sh">"</span><span class="p">,</span>
            <span class="sh">"</span><span class="s">space</span><span class="sh">"</span><span class="p">:</span> <span class="p">{</span>
                <span class="sh">"</span><span class="s">key</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">mySpaceNameGoesHere</span><span class="sh">"</span>
            <span class="p">},</span>
            <span class="sh">"</span><span class="s">body</span><span class="sh">"</span><span class="p">:</span> <span class="p">{</span>
                <span class="sh">"</span><span class="s">storage</span><span class="sh">"</span><span class="p">:</span> <span class="p">{</span>
                    <span class="sh">"</span><span class="s">representation</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">storage</span><span class="sh">"</span><span class="p">,</span>
                    <span class="sh">"</span><span class="s">value</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">Meeting description goes here.</span><span class="sh">"</span>
                <span class="p">}</span>
            <span class="p">}</span>
            <span class="c1">#"history": {
</span>            <span class="c1">#    "createdDate": '2017-01-10T14:00:00.000Z'
</span>            <span class="c1">#},
</span>
        <span class="p">}</span>

<span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="nf">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> 
                         <span class="n">data</span><span class="o">=</span><span class="n">json</span><span class="p">.</span><span class="nf">dumps</span><span class="p">(</span><span class="n">payload</span><span class="p">),</span> 
                         <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span> 
                         <span class="n">auth</span><span class="o">=</span><span class="p">(</span><span class="sh">"</span><span class="s">myUserName</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">mySecretPassword</span><span class="sh">"</span><span class="p">))</span>
<span class="k">print</span> <span class="n">json</span><span class="p">.</span><span class="nf">dumps</span><span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="nf">json</span><span class="p">(),</span> <span class="n">indent</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="n">sort_keys</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span></code></pre></figure>

<p>You should be able to run this script against your end-point and post your content. Just note that I used <code class="language-plaintext highlighter-rouge">requests</code> library here that needs to be installed separately, for instance, by using <code class="language-plaintext highlighter-rouge">pip</code>:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo </span>pip <span class="nb">install </span>requests</code></pre></figure>

<p>Also, you will need to update the following values in the script:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">url</code> &#8211; the URL to your site</li>
  <li><code class="language-plaintext highlighter-rouge">type</code> &#8211; can be a <code class="language-plaintext highlighter-rouge">blogpost</code> or a <code class="language-plaintext highlighter-rouge">page</code></li>
  <li><code class="language-plaintext highlighter-rouge">title</code> &#8211;&#160;page or post title</li>
  <li><code class="language-plaintext highlighter-rouge">space</code> &#8211; a Confluence space where the post will belong</li>
  <li><code class="language-plaintext highlighter-rouge">value</code> &#8211; content of the page, can contain HTML tags</li>
  <li><code class="language-plaintext highlighter-rouge">auth</code> &#8211;&#160;username and password (please note that, for security reasons, it might be a good idea to create a separate user with restricted access rights just for posting specific content)</li>
  <li><code class="language-plaintext highlighter-rouge">createdDate</code> &#8211; you can also add the commented-out part to add a specific blog post date</li>
</ul>

<p>The script uses basic authentication to post the content and, if successful, returns metadata about the post as a response. If it fails, the response from Confluence end-point should point you in the right direction.</p>

<hr />

<h2 id="creating-a-lambda-function-in-aws">Creating a Lambda Function in AWS</h2>

<p>Now we are one step closer to automation. The script works, and we can post content with a simple push of a button. What now?</p>

<p>Well, now I needed something to run that script and something to trigger that action. The trigger is the time as I wanted to run our script weekly, but first I needed to deploy our script to the Cloud. Scheduling and triggers would come later.</p>

<p>Since we had some infrastructure on AWS already, I decided to deploy the script on the same platform. I wanted to deploy it as a simple stand-alone function in the Cloud &#8211; in AWS world it is called a <a href="http://docs.aws.amazon.com/lambda/latest/dg/welcome.html" target="_blank">Lambda function</a>.</p>

<p>I started by wrapping our code into a function and making it AWS Lambda function compatible &#8211; to define a function that takes two arguments: <code class="language-plaintext highlighter-rouge">event</code> and <code class="language-plaintext highlighter-rouge">context</code>. I choose to call the function <code class="language-plaintext highlighter-rouge">blogpost_handler</code>:</p>

<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1">#!/usr/bin/python
# -*- coding: utf-8 -*-
</span>
<span class="c1"># File name: poster.py
</span>
<span class="kn">import</span> <span class="n">requests</span>
<span class="kn">import</span> <span class="n">json</span>
<span class="kn">import</span> <span class="n">datetime</span>

<span class="k">def</span> <span class="nf">blogpost_handler</span><span class="p">(</span><span class="n">event</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> 

    <span class="c1"># Script is run on Sunday, need to use date for Tuesday
</span>    <span class="n">next_tue</span> <span class="o">=</span> <span class="p">(</span><span class="n">datetime</span><span class="p">.</span><span class="n">datetime</span><span class="p">.</span><span class="nf">now</span><span class="p">()</span>
                    <span class="o">+</span><span class="n">datetime</span><span class="p">.</span><span class="nf">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">2</span><span class="p">)).</span><span class="nf">strftime</span><span class="p">(</span><span class="sh">"</span><span class="s">%Y-%m-%d</span><span class="sh">"</span><span class="p">)</span>

    <span class="n">url</span> <span class="o">=</span> <span class="sh">"</span><span class="s">https://some-confluence-url.com/rest/api/content/</span><span class="sh">"</span>
    <span class="n">headers</span> <span class="o">=</span> <span class="p">{</span> <span class="sh">"</span><span class="s">content-type</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">application/json</span><span class="sh">"</span> <span class="p">}</span>
    <span class="n">payload</span> <span class="o">=</span> <span class="p">{</span> <span class="sh">"</span><span class="s">type</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">blogpost</span><span class="sh">"</span><span class="p">,</span>
                <span class="sh">"</span><span class="s">title</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">Meeting: </span><span class="sh">"</span><span class="o">+</span><span class="n">next_tue</span><span class="p">,</span>
                <span class="sh">"</span><span class="s">space</span><span class="sh">"</span><span class="p">:</span> <span class="p">{</span>
                    <span class="sh">"</span><span class="s">key</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">mySpaceNameGoesHere</span><span class="sh">"</span>
                <span class="p">},</span>
                <span class="sh">"</span><span class="s">body</span><span class="sh">"</span><span class="p">:</span> <span class="p">{</span>
                    <span class="sh">"</span><span class="s">storage</span><span class="sh">"</span><span class="p">:</span> <span class="p">{</span>
                        <span class="sh">"</span><span class="s">representation</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">storage</span><span class="sh">"</span><span class="p">,</span>
                        <span class="sh">"</span><span class="s">value</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">Meeting description goes here.</span><span class="sh">"</span>
                    <span class="p">}</span>
                <span class="p">}</span>
            <span class="p">}</span>

    
    <span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="nf">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> 
                             <span class="n">data</span><span class="o">=</span><span class="n">json</span><span class="p">.</span><span class="nf">dumps</span><span class="p">(</span><span class="n">payload</span><span class="p">),</span> 
                             <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span> 
                             <span class="n">auth</span><span class="o">=</span><span class="p">(</span><span class="sh">"</span><span class="s">myUserName</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">mySecretPassword</span><span class="sh">"</span><span class="p">))</span>
    
    <span class="k">print</span> <span class="n">json</span><span class="p">.</span><span class="nf">dumps</span><span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="nf">json</span><span class="p">(),</span> <span class="n">indent</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="n">sort_keys</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">response</span><span class="p">.</span><span class="nf">json</span><span class="p">()</span></code></pre></figure>

<p>Now, I needed <a href="http://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html" target="_blank">to package</a> the code to make it ready to deploy:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># 1. create folder</span>
<span class="nb">mkdir </span>blogposter
<span class="nb">cd </span>blogposter

<span class="c"># 2. create and copy the code above into poster.py</span>
<span class="nb">touch </span>poster.py

<span class="c"># 3. install requests package locally</span>
pip <span class="nb">install </span>requests <span class="nt">-t</span> <span class="nb">.</span>

<span class="c"># 4. zip contents of the folder and create a zip file in a parent directory</span>
zip <span class="nt">-r9</span> ../pyposter.zip <span class="k">*</span></code></pre></figure>

<p>And we are ready to deploy to AWS! Start with creating a new Lambda Function and selecting a blank function for this job.</p>

<p><img src="/assets/images/posts-images/2017-01-29-confluence-and-aws_screen1.png" alt="Start with selecting a blueprint" /></p>

<p>I didn&#8217;t choose any triggers for now and continued to the configuration page. When presented with function configuration you need to give it a name, description, runtime, and a .zip file with the code. At the end, you will need to define a handler (which will typically be <code class="language-plaintext highlighter-rouge">filename.function_name</code>), and a role.</p>

<p><img src="/assets/images/posts-images/2017-01-29-confluence-and-aws_screen2.png" alt="Fill out the rest of info" /></p>

<p>At the end of the wizard, you can run it manually by pressing the Test button. If you did all the steps above, this should now create a new post on your Confluence. Congratulations, you have now set up a stand-alone function in the Cloud!</p>

<hr />

<h2 id="schedule-it">Schedule it!</h2>

<p>Now that I have automated the task and deployed it to the Cloud, I needed something to trigger that function. In this case, I wanted to schedule it to run weekly, so function was set to be triggered by the <a href="http://docs.aws.amazon.com/lambda/latest/dg/with-scheduled-events.html" target="_blank">CloudWatch</a> events. It offers a good support for <a href="http://docs.aws.amazon.com/AmazonCloudWatch/latest/events/RunLambdaSchedule.html" target="_blank">scheduling Lambda expressions</a>.</p>

<p>I defined event source as a cron expression, and a target as a Lambda function I created in the previous step.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># 9:05, every Sunday</span>
5 9 ? <span class="k">*</span> 1 <span class="k">*</span></code></pre></figure>

<p><img src="/assets/images/posts-images/2017-01-29-confluence-and-aws_screen3.png" alt="Adding a scheduled event" /></p>

<p>Now you (and I) have a function that is scheduled to run weekly and does not require a dedicated machine to run. It also has some good options for logging and sending alarms in case it fails.</p>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">Automating posting to Confluence with cloud services like Amazon Web Services (AWS).</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/clouds.jpg"/><category term="blog"/><category term="field notes"/><category term="automation"/><category term="cloud"/><category term="python"/><category term="english"/></entry></feed>
