#!/usr/bin/python
""" This module provide a MirrorClient class that listen to a Mirror device
(from Violet). This class is a little adaptation to a twisted oriented code
found in the following article http://www.dad3zero.net/201012/mirror-en-python/
"""


import binascii
from time import sleep
from twisted.internet import reactor


class MirrorClient(object):
    """ The MirrorClient listen to a device (eg: /dev/mirror) and call the
    registered callbacks (from add_callback method) with the tag and
    associtated state of the tag.
    """
    def __init__(self, device):
        """ Init the MirrorClient with an associated device to listen.
        """
        self.device_name = device
        self.subscribers = set()
        self._open()

    def _open(self):
        try:
            self.device = open(self.device_name, 'rb')
        except IOError:
            self.device = None

    def start(self):
        """ When the start method is called, the listen method is called inside
        a thread.
        """
        reactor.callInThread(self.listen)

    def subscribe(self, callback):
        """ Add a callback which will be called when an event is read from the
        defined device.
        """
        self.subscribers.add(callback)

    def listen(self):
        """ Listen until the reactor is stopped and read the device. When a tag
        is detected or removed call registered callbacks.
        """
        while reactor.running:
            if not self.device or self.device.closed is True:
                self.device_disconnected()
            else:
                try:
                    data = self.device.read(16)
                    if data != '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00':  # pylint: disable=C0301
                        bin_state = binascii.hexlify(data)[:4]
                        tag = binascii.hexlify(data)[4:]
                        # Sometime a ghost tag is detected by the Mirror device.
                        if bin_state != '0104':
                            state = True if bin_state == '0201' else False
                            reactor.callFromThread(self.data_received, tag, state)
                except IOError:
                    self.device.close()

    def device_disconnected(self):
        """ When the mirror is disconnected from the computer wait 500ms
        and try to reopen the device.
        """
        sleep(0.5)
        self._open()

    def data_received(self, tag, state):
        """ Call all registered callbacks.
        """
        for subscriber in self.subscribers:
            subscriber(tag, state)

@@ -665,24 +665,25 @@
        self.
+_
 device_name 
@@ -696,32 +696,33 @@
 ce%0A        self.
+_
 subscribers = se
@@ -790,32 +790,33 @@
            self.
+_
 device = open(se
@@ -814,24 +814,25 @@
 = open(self.
+_
 device_name,
@@ -875,24 +875,25 @@
        self.
+_
 device = Non
@@ -1060,16 +1060,17 @@
 ad(self.
+_
 listen)%0A
@@ -1229,24 +1229,25 @@
        self.
+_
 subscribers.
@@ -1269,16 +1269,17 @@
     def 
+_
 listen(s
@@ -1485,24 +1485,25 @@
 if not self.
+_
 device or se
@@ -1501,24 +1501,25 @@
 ice or self.
+_
 device.close
@@ -1546,24 +1546,25 @@
        self.
+_
 device_disco
@@ -1640,24 +1640,25 @@
 data = self.
+_
 device.read(
@@ -2165,16 +2165,17 @@
 ad(self.
+_
 data_rec
@@ -2250,16 +2250,17 @@
    self.
+_
 device.c
@@ -2275,16 +2275,17 @@
     def 
+_
 device_d
@@ -2475,16 +2475,17 @@
     def 
+_
 data_rec
@@ -2595,16 +2595,17 @@
 in self.
+_
 subscrib

Add underscore to private methods and attributes