Пример #1
0
class SwitcherCom(object):

    cmd_off = 'OFF'
    cmd_on = 'ON'
    cmd_status = 'STATUS'
    cmd_reload = 'RELOAD'
    cmd_gpio_pin = 'GPIO{0:02d}'

    state_on = 'ON'
    state_off = 'OFF'
    state_unknow = None

    resp_error = 'ERROR'
    resp_timeout = 'TIMEOUT'
    resp_ok = 'OK'
    resp_reloading = 'RELOADING'
    reps_configured = 'CONFIGURED'

    def __init__(self, log):
        self._log = log
        self.comm = Comunicator(
            Comunicator.MODE_CLIENT, SWITCHER_PIPE_IN, SWITCHER_PIPE_OUT, log
        )

    def send_command(self, command):

        response = None

        if self.comm.send_message(os.getpid(), command, timeout=15):
            self._log.info("Inviato comando %s", command)
            response = self.comm.read_message()
        else:
            return self.resp_error

        return response[1]

    def is_response_ok(self, response):
        return response[0:2] == self.resp_ok

    def get_response_msg(self, response):
        return response[3:].strip()
Пример #2
0
class Switcher(Daemon):

    DEF_LOG_LEVEL = WARNING

    def __init__(
        self, pidfile, stdin='/dev/null', stdout='/dev/null',
        stderr='/dev/null', logfile='/dev/null', invert_state=False
    ):
        super(Switcher, self).__init__(pidfile, stdin, stdout, stderr, logfile)
        self.invert_state = invert_state

    def run(self):

        # Configuro le pipe di comunicazione
        self.comm = Comunicator(
            Comunicator.MODE_SERVER, SWITCHER_PIPE_IN,
            SWITCHER_PIPE_OUT, self.log)

        if self.invert_state:

            self.STATE_ON, self.STATE_OFF = GPIO.LOW, GPIO.HIGH
            self.log.debug(
                'Stato ON -> GPIO.LOW (%s), Stato OFF -> GPIO.HIGH (%s)',
                GPIO.LOW, GPIO.HIGH)
        else:

            self.STATE_ON, self.STATE_OFF = GPIO.HIGH, GPIO.LOW
            self.log.debug(
                'Stato ON -> GPIO.HIGH (%s), Stato OFF -> GPIO.LOW (%s)',
                GPIO.HIGH, GPIO.LOW)

        # Init GPIO Board
        self.log.debug(
            'Inizializzazione GPIO: revisione %s', GPIO.RPI_REVISION)

        # Registro funzioni reload e uscita
        signal.signal(signal.SIGHUP, self._load_config)
        signal.signal(signal.SIGTERM, self._cleanup)

        state = self.STATE_OFF
        self.reset_state = True
        self.pin = None

        while True:

            if self.reset_state:
                # In attesa di configurazione pin GPIO
                self.pin = self._wait_for_gpio_pin()
                state = self.STATE_OFF
                self.reset_state = False

            # Attendo un nuovo comando
            msg = self.comm.read_message(None)
            cmd = msg[1]
            self.log.debug("Ricevuto comando: %s", cmd)

            if cmd == 'ON' or cmd == 'OFF':

                response = 'OK:%s' % (cmd)
                res = True

                if cmd == 'ON' and state != self.STATE_ON:
                    res = self._set_pin_on(self.pin)

                elif cmd == 'OFF' and state != self.STATE_OFF:
                    res = self._set_pin_off(self.pin)

                if not res:
                    response = "ERROR"
                else:
                    state = self.STATE_ON if cmd == 'ON' else self.STATE_OFF

            elif cmd == 'STATUS':
                response = 'OK:%s' % (self._get_pin_status(self.pin, state))

            elif cmd == 'RELOAD':
                self.log.warning("Ricarico configurazione...")
                self.reset_state = True
                response = "OK:RELOADING"
                GPIO.cleanup()

            elif cmd == 'TIMEOUT':
                self.log.info("Timeout in lettura")
                continue

            else:
                response = 'ERROR'

            self.log.debug("Invio risposta: %s", response)
            # Attendo qualche istante per sincronizzare l'actuator
            time.sleep(0.5)
            self.comm.send_message(getpid(), response, timeout=15)

    def _load_config(self, signum, frame):
        self.log.warning(
            "Ricevuto segnale %s frame %s: ricarico configurazione",
            signum, frame)

        GPIO.cleanup()
        self.reset_state = True

    def _cleanup(self, signum, frame):

        self.log.warning(
            "Ricevuto segnale %s frame %s: uscita", signum, frame)
        GPIO.setwarnings(False)
        GPIO.cleanup()
        exit(0)

    def _set_pin_on(self, pin):
        return self._set_pin_state(pin, self.STATE_ON)

    def _set_pin_off(self, pin):
        return self._set_pin_state(pin, self.STATE_OFF)

    def _set_pin_state(self, pin, state):

        stato_raw = 'HIGH' if state == GPIO.HIGH else 'LOW'

        try:
            GPIO.output(pin, state)
            self.log.debug("Pin: %s impostato in %s", pin, stato_raw)
            ret = True

        except Exception as e:
            self.log.error(
                "Impossibile commutare pin %s in %s: %s",
                pin, stato_raw, repr(e))
            ret = False

        return ret

    def _get_pin_status(self, pin, raw_state):

        state = 'ON' if raw_state == self.STATE_ON else 'OFF'
        self.log.debug("Pin: %s stato %s", pin, state)
        return state

    def _wait_for_gpio_pin(self):

        pin = None

        self.log.info("Attendo configurazione pin GPIO")

        while pin is None:
            msg = self.comm.read_message(None)
            gpio = msg[1]

            if 'GPIO' in gpio:
                try:
                    pin = int(gpio[-2:])
                    # Modo numerazione pin: Broadcom's SoC
                    GPIO.setmode(GPIO.BCM)
                    # Init del relè default off
                    GPIO.setup(pin, GPIO.OUT, initial=self.STATE_OFF)
                    self.log.info('Configuro GPIO %s per Relè', pin)
                    self.comm.send_message(getpid(), 'OK:CONFIGURED')

                except Exception as e:
                    pin = None
                    self.log.error(
                        'Impossibile inizializzare il pin GPIO %s', repr(e))
            else:
                self.comm.send_message(getpid(), 'ERROR', timeout=5)
                self.log.warning('Ignorato messaggio %s', msg)

        return pin