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

Monday, 24 July 2017

Controlling mains AC or DC via raspberry Pi and Alexa

Controlling mains AC or DC via Raspberry Pi via Alexa

Background

I have LED strip lights, lighting the floating wall, and want to control them via Alexa. The raspberry pi will be doing the actual switching.

There is a decent library which emulates a belkin wemo switch called fauxmo and Alexa can control Belkin's Wemo switches.

Requirements:

  • Raspberry Pi (I will be using a 3 model b)
  • Opto relays (I Bought mine from Amazon UK https://www.amazon.co.uk/gp/product/B06XK6HCQC/ref=oh_aui_search_detailpage?ie=UTF8&psc=1 )
  • Amazon echo or echo dot 
  • Wires and a breadboard

Wiring

  •  Install N00bs, following the raspberry pi guide here: https://www.raspberrypi.org/documentation/installation/noobs.md
  • Attach everything (I am using a breadboard), according to this pinout (raspberry pi 2/3 specific)  

So:
GND on the relay -> GND on the raspberry Pi
IN1,2,3,4 -> GPIO 2,3,4,17
VCC -> 5v power.

As of writing this, n00bs, has all the pre-reqs pretty much installed already, but you will need to double check, using this excellent guide from adafruit ( https://learn.adafruit.com/adafruits-raspberry-pi-lesson-4-gpio-setup/configuring-gpio )

Testing

Write some test code to check it all works (this will need to be run as root)
Change the GPIO numbers according to your setup.

#!/usr/bin/python
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

# init list with pin numbers
pinList = [2, 3, 4, 20, 21]

# loop through pins and set mode and state to 'high'

for i in pinList:
    GPIO.setup(i, GPIO.OUT)
    GPIO.output(i, GPIO.LOW)
    print i

print "ALL SET LOW"
# time to sleep between operations in the main loop

SleepTimeL =3
time.sleep(SleepTimeL);

# main loop

try:
  time.sleep(SleepTimeL);
  GPIO.output(2, GPIO.HIGH)
  print "TWO"
  time.sleep(SleepTimeL);
  GPIO.output(3, GPIO.HIGH)
  print "THREE"
  time.sleep(SleepTimeL);
  GPIO.output(4, GPIO.HIGH)
  print "FOUR"
  time.sleep(SleepTimeL);
  GPIO.output(20, GPIO.HIGH)
  print "20"
  time.sleep(SleepTimeL);
  GPIO.output(21, GPIO.HIGH)
  print "21"
  time.sleep(SleepTimeL);
  print "Good bye!"
  for i in pinList:
    GPIO.output(i, GPIO.LOW)
  #  GPIO.cleanup()

# End program cleanly with keyboard
except KeyboardInterrupt:
  print "  Quit"

  # Reset GPIO settings
  GPIO.cleanup()

Alexa integration

pip install fauxmo

Check the code out in my repo: https://bitbucket.org/c240amg/raspberry-pi-alexa/src/



Sunday, 10 April 2016

Hacking the Amazon Dash for the UK

 Intro

So you want to use the Amazon Dash button but live in the UK?First issue, is actually getting them. They are only available in the US and you require a US address. Once you've actually obtained one of them, the next bit is pretty easy...

Configuration- android

Well you have to setup the dash button through the amazon.com app....

The easiest thing to do is to press and hold the dash until it flashes blue. Once it is in this mode, it creates a access point called 'Amazon ConfigureMe'. I used the excellent tool iStumbler to find this:


Once connected to it (192.168.0.2), I used firefox to http://192.168.0.1

There I entered the SSID and password of my local wireless LAN network and bam. It gave me the success sceen.


This, unfortunately, did not work, because the amazon app has a cert which automagically activates the dash, and in part of that process requires you to have a US IP address. So I fired up openvpn and connected to an endpoint in the US then did the setup via the amazon app.

Each time the dash connects to my wireless LAN, it sends a gratuitous arp and then shuts down. Note that the configuration mac address ( 6c:0b:84:34:ce:ed )is different to the actual mac address it uses once setup.

Programming

I am using my current favourite language python, and we're going to use the scapy library.
Firstly, we need to install the library:
sudo pip install scapy
Then run this script to find out what the mac address is:
from scapy.all import *


def arp_display(pkt):
  if pkt[ARP].op == 1: #who-has (request)
    if pkt[ARP].psrc == '0.0.0.0': # ARP Probe
      print "ARP Probe from: " + pkt[ARP].hwsrc

print sniff(prn=arp_display, filter="arp", store=0, count=10)
 
So now that I know this I can plug this into a proper python program, which sends me an email when my 9month old baby poos.
from scapy.all import *
import smtplib
server = smtplib.SMTP('192.168.2.254', 25)


def arp_display(pkt):
  if pkt[ARP].op == 1: #who-has (request)
    if pkt[ARP].psrc == '0.0.0.0': # ARP Probe
      if pkt[ARP].hwsrc == 'a0:02:dc:88:94:ea': # digestive disadvantage
        print "Pushed Poo"
    msg = "Scarlett pooed" # The /n separates the message from the headers
    server.sendmail("dash@amz.org", "phil.spencer@gmail.com", msg)   
  
      elif pkt[ARP].hwsrc == '10:ae:60:b1:97:73': # Depends
        print "Pushed Depends button"
      else:
        print "ARP Probe from unknown device: " + pkt[ARP].hwsrc

while True:
  print sniff(prn=arp_display, filter="arp", store=0, count=10)
 
Next part I will show how to log this data into an Excel sheet for later analysis.


Tuesday, 27 August 2013

KVM domain lists (list of guests on KVM)

As we're moving towards virtualisation in our datacentre, we decided to go with KVM.

Sadly, there was no web interface to view them, so I created one in python. This runs in the background.

#!/usr/bin/env python
#
# Starts up webserver and runs forever
# lists domains running and defined
# pks - 20130405
# pks - add console

import re, os, sys, string, optparse
import xml.etree.ElementTree as ElementTree
import libvirt
import socket
import commands
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer

Port_Number=80

conn = libvirt.openReadOnly(None) 
assert conn, 'Failed to open connection'

names = conn.listDefinedDomains()
domains = map(conn.lookupByName, names)

ids = conn.listDomainsID()
running = map(conn.lookupByID, ids)

columns = 3

states = {
    libvirt.VIR_DOMAIN_NOSTATE: 'no state',
    libvirt.VIR_DOMAIN_RUNNING: 'running',
    libvirt.VIR_DOMAIN_BLOCKED: 'blocked on resource',
    libvirt.VIR_DOMAIN_PAUSED: 'paused by user',
    libvirt.VIR_DOMAIN_SHUTDOWN: 'being shut down',
    libvirt.VIR_DOMAIN_SHUTOFF: 'shut off',
    libvirt.VIR_DOMAIN_CRASHED: 'crashed',
}
def info(dom):
    [state, maxmem, mem, ncpu, cputime] = dom.info()
    return '%s is %s,' % (dom.name(), states.get(state, state))

class myHandler(BaseHTTPRequestHandler):
  def do_GET(self):
    self.send_response(200)
    self.send_header('Content-type','text/html')
    self.end_headers()
    print 'Defined domains:'
    self.wfile.write ('<b>Defined domains:</b>')
    self.wfile.write ('</br>')
    for row in map(None, *[iter(domains)] * columns):
      for domain in row:
        if domain:
          print info(domain),
          print
          self.wfile.write (info(domain))
          self.wfile.write ('</br>')
    print 'Running domains:'
    self.wfile.write ('<b>Running domains:</b>')
    self.wfile.write ('</br>')
    for row in map(None, *[iter(running)] * columns):
      for domain in row:
        if domain:
          server=info(domain).partition(" ")
          execstring="/usr/local/bin/vm.sh vnc %s" % server[0]
          output=commands.getstatusoutput(execstring)
          vnc=output[1].split(" ")
          vncport=vnc[5]
          print info(domain)
          print vncport


          nic=socket.gethostbyname(socket.gethostname())
          self.wfile.write ("<a href=\"vnc://%s:%s\"> %s </a>" % (nic, vncport ,info(domain)))
          self.wfile.write ('</br>')

try:
  server = HTTPServer(('',Port_Number), myHandler)
  print "Started HTTP server on port", Port_Number
  server.serve_forever()


except KeyboardInterrupt:
  print 'CTRL+C received. Shutting down webserver'
  server.socket.close()
 
All you have to do is surf to port 80 (or modify the script so that  it points to your port of choice) then you could run from your central monitoring machine etc a script which grabs all the KVM hosts info and display it in one whole page.

An example would be this in PHP, where out servers on on the subnet 10.3.117.101 to 114. It also highlights all servers with the name 'testweb'
<html>
<head>

</head>
<body>
<h1>LN1</h1>
<table border=1>
<tr>
<?
    for ($i=1 ; $i <15 ; $i++)
    {
        echo "<td>";
        echo "<a href=\"http://10.3.117.".($i+100)."\">KVM".($i)."</a>";
        echo "</td><td>";
        $ip=100+$i;
        #$test=exec("curl -s http://10.3.117.$ip  | awk 'gsub(/ *<[^>]*> */,\" \")'");
        $test=exec("curl -s http://10.3.117.$ip");
        $test=str_replace("Running domains:","<b>Running domains:</b>",$test);
        $test=str_replace("Defined domains:","<b>Defined domains:</b>",$test);
        $test=str_replace("</br>","",$test);
        #$test=str_replace("testweb","<font color=6666ff>testweb</font>",$test);
        $test=str_replace("is running","",$test);
        echo $test;
        echo "</td></tr><tr>";
        echo "\n\r";
    }

?>
</tr>
</table>

</body>
</html>




Thursday, 31 March 2011

A more advanced check_mk check i've written for linux_ulimits


#!/bin/python


inventory_process = []
inventory_process_version = []
def inventory_linux_ulimit (checkname, info):
        inventory = []
        if checkname == "linux_ulimit":
                #print "linux ulimit inv"
                #print info
                for line in info:
                        ln1 = line[0]
                        ln2 = line[1]
                ln1 = int(ln1)
                ln2 = int(ln2)
                #print "%d %d" % (ln1, ln2)
                value = "%d / %d" % (ln1, ln2)
                inventory.append ( ("Ulimit", (ln1,ln2)))
                return inventory






#the actual check


def check_linux_ulimit (item, params, info):
        perfdata = []

        perfdata = (float((params[0])/float(params[1]))*100.0)
        #value = ("Cur=%d ; Max=%d" % (params[0], params[1]))
        value = [("ulimit_cur",params[0],params[1]),]
        #print value
        if perfdata > 90.0:
                return (2, "Critical@90%: %d of %d used. %.1f%%" % (params[0],params[1],perfdata), value)
        if perfdata > 85.0:
                return (1, "Warning@85: %d of %d used. %.1f%%" % (params[0], params[1],perfdata),value)


        return (0, "OK - %d of %d used. %.1f%% " % (params[0], params[1],perfdata), value)


# checking function, service description, perf data, invenotry function
check_info['linux_ulimit'] = (check_linux_ulimit, "Linux",1 ,inventory_linux_ulimit)