Example #1
0
class Stop:
    ''' Create a object to store a stop with relation to its rgb pin mappings'''
    def __init__(self, name, arrival_time, red, green, blue):
        self.name = name
        self.arrival_time = arrival_time
        self.light = RGBLED(red, green, blue)
        self.colors = {
            'red': (1, 0, 0),
            'blue': (0, 0, 1),
            'green': (0, 1, 0),
            'yellow': (1, 1, 0),
        }

    def pulse(self, color):
        self.light.pulse(fade_in_time=.7,
                         fade_out_time=.3,
                         on_color=color,
                         off_color=(0, 0, 0),
                         background=True)
        return

    def color_decider(self):
        ''' Set light to be color/pulse depending on how long until the muni is coming'''
        self.light.on()
        if self.arrival_time in (0, 1, 2):
            self.pulse(self.colors['red'])
        elif self.arrival_time in (3, 4):
            self.pulse(self.colors['green'])
        elif self.arrival_time in (5, 6, 7, 8):
            self.light.color = self.colors['green']
        elif self.arrival_time in (9, 10, 11, 12, 13, 14, 15):
            self.light.color = self.colors['yellow']
        elif self.arrival_time > 15:
            self.light.color = self.colors['blue']
        else:
            raise Exception(
                'Unexpected else in color decider on arrival_time value: {}'.
                format(self.arriva_time))
        return

    def cycle_colors(self):
        '''
		 	Cycling colors indicates to users that the lights are updating 
		'''
        self.light.on()
        self.light.color = self.colors['red']
        time.sleep(.5)
        self.light.color = self.colors['green']
        time.sleep(.5)
        self.light.color = self.colors['blue']
        time.sleep(.5)
        self.light.color = self.colors['yellow']
        time.sleep(.5)
        self.light.off()
Example #2
0
class CHFSM:

    # Normal operation
    IDLE_COLOUR = (1.5, 1.5, (0, 0, 0), (1.0, 1.0, 1.0))  # off to White
    CH_ONLY_COLOUR = (1.5, 1.5, (0, 0, 0), (0, 0.9, 0.4)
                      )  # off to Reddy-purple
    HW_ONLY_COLOUR = (1.5, 1.5, (0, 0, 0), (0.9, 0.0, 0.1)
                      )  # off to Greeny-cyan
    CH_AND_HW_COLOUR = (1.5, 1.5, (0, 0, 0), (0.9, 0.1, 0.0))  # off to Orange
    # INHIBIT_MODE = (1.5, 1.5, (0,0,0), (1, 0, 0.5))  # Off to purple

    # Errors
    NO_GATEWAY_CONNECTION = (1.5, 1.5, (1, 0, 0), (0.9, 0, 0.9)
                             )  # Red to purple
    SCHEDULE_MISSING = (1.5, 1.5, (1, 0, 0), (1, 0.3, 0.0)
                        )  # red to yellow/orange
    BAD_SCHEDULE = (1.5, 1.5, (1, 0, 0), (1, 1, 0))  # red to cyan

    # Maintainance mode
    BLUETOOTH_MODE = (1.5, 1.5, (0, 0, 1), (0, 1, 1))  # blue to cyan
    UPDATING = (1.5, 1.5, (0, 0, 1), (0, 1, 0))  #blue to Green

    update_time = config[r"update_time"]

    # Update and reboot time (day_of_month, hour, minute, second)
    UPDATE_REBOOT_TIME = (update_time["day_of_month"], update_time["hour"],
                          update_time["minute"], update_time["second"])

    PULSE_UP_TIME = 1.5
    PULSE_DOWN_TIME = 1.5

    BUTTON_BOUNCE_TIME = None

    # The duration of a CH or HW boost, in seconds
    BOOST_DURATION = config["boost_duration"]

    def __init__(self, red, green, blue, hw_relay, ch_relay, hw_button,
                 ch_button, rgb_active_high, ch_relay_active_high,
                 hw_relay_active_high):

        # Setup push buttons
        self.ch_button = BetterButton(ch_button, self.chPressed,
                                      self.BUTTON_BOUNCE_TIME, None, True)
        self.hw_button = BetterButton(hw_button, self.hwPressed,
                                      self.BUTTON_BOUNCE_TIME, None, True)

        # Setup relay
        self.hw_relay = DigitalOutputDevice(hw_relay, hw_relay_active_high)
        self.ch_relay = DigitalOutputDevice(ch_relay, ch_relay_active_high)

        # Setup RGB status LED
        self.status_led = RGBLED(red, green, blue, active_high=rgb_active_high)

        self.commands_file_path = config["commands_path"]
        self.schedule_file_path = config["schedule_path"]

        # Setup HW boost objects
        self.hw_boost_start = None
        self.ch_boost_on = False

        self.hw_pressed_flag = False
        self.ch_pressed_flag = False

        # Load first state
        self.state = IdleState(self)
        self.state.enter()

        #
        self.last_gateway_ping = datetime.now()

    def close(self):
        self.status_led.close()
        self.hw_relay.close()
        self.ch_relay.close()

    def setState(self, state):
        self.state.leave()
        self.state = state
        logging.debug("State change: %s", type(state))
        self.state.enter()

    def process(self):
        self.state.process()

    def getState(self):
        return self.state

    def chPressed(self):
        logging.debug("CH button press")
        self.ch_pressed_flag = True

    def hwPressed(self):
        logging.debug("HW button press")
        self.hw_pressed_flag = True

    def setStatusLed(self, colour):
        self.status_led.pulse(colour[0],
                              colour[1],
                              off_color=colour[2],
                              on_color=colour[3])

    def parent_folder():
        return os.path.dirname(os.path.dirname(__file__))
# Import libraries
import RPi.GPIO as GPIO
from time import sleep
from signal import pause
from gpiozero import RGBLED

# Write all codes inside try statement
try:
    led = RGBLED(
        17, 27, 22,
        active_high=False)  # Set active_high to False for common anode
    led.pulse(on_color=(0.1, 0.3, 0.4))
    pause()

# except statement to handle user's keyboard interrupt
except KeyboardInterrupt:
    print("Stopping python script...")
    print("Cleaning up GPIO...")

# finally statement will run before exiting try statement
finally:
    GPIO.cleanup()
    print("Cleaning completed!")
    print("Exit program")
Example #4
0
class LED:
    def __init__(self, red, green, blue, verbose=False):
        self.led = RGBLED(red, green, blue)
        self.bright = 1
        self.thread = Thread()
        self.stop_thread = False
        self.verbose = verbose
        if AUTODIM:
            t = Thread(target=self.autoDimming, daemon=True)
            t.start()
        self.changeLights(LightChanges.instant, DEFAULT_COLOR)
        self.dprint('lights init')

    def handle(self, payload):
        #kill old thread
        self.killThread()

        #handle brightness
        if payload in LED_bright_terms:
            self.dprint('brightness to {}'.format(payload))
            self.bright = LED_bright_terms[payload]
            self.changeLights(self.change_type, self.color)
            return True

        change_type = LightChanges.transition
        #handle toggle/on/off/stop
        if payload == 'toggle':
            self.dprint('toggle')
            if self.led.is_lit:
                self.led.off()
            else:
                self.changeLights(change_type, self.color)
            return True
        if payload == 'off':
            self.dprint('off')
            self.led.off()
            return True
        if payload == 'on':
            self.dprint('on')
            self.changeLights(change_type, self.color)
            return True
        if payload == 'stop':
            self.dprint('stop')
            self.led.color = self.led.color
            return True

        color = payload
        if 'pulse' in payload:
            color = payload.replace('pulse', '').replace(' ', '')
            if color == '':
                color = self.color
            change_type = LightChanges.pulse
        elif 'rain' in payload:
            color = 'black'
            change_type = LightChanges.rainbow

        #handle color
        self.thread = Thread(target=self.changeLights,
                             args=(change_type, color),
                             daemon=True)
        self.thread.start()
        return True

    def changeLights(self, type, colortext='black'):
        try:
            color = Color(colortext)
        except ValueError:
            self.dprint('error while trying to parse {}'.format(colortext))
            return False
        self.dprint('change type {} to {}{}{}'.format(type, color, color.rgb,
                                                      Color('white')))
        self.change_type = type
        switcher = {
            LightChanges.instant: self.setColor,
            LightChanges.transition: self.chgTrans,
            LightChanges.pulse: self.chgPulse,
            LightChanges.rainbow: self.chgRain
        }
        switcher.get(type, lambda x: self.dprint('invalid input'))(color)
        return True

    def setColor(self, color, ignore_bright=False):
        self.color = color
        self.led.color = self.applyBright(
            color) if ignore_bright is False else color
        self.dprint('set color to {}{}{}'.format(color, color.rgb,
                                                 Color('white')))

    def applyBright(self, color):
        if self.bright == 1:
            return color
        else:
            return Color(tuple(self.bright * x for x in color))

    def chgTrans(self,
                 new_color,
                 ignore_bright=False,
                 duration=TRANSITION_DURATION):
        N = REFRESH_RATE * duration
        #total color difference
        diff = []
        for n, c in zip(new_color, self.led.color):
            diff.append(n - c)
        self.color = self.led.color

        #color change per update
        step = tuple(x / N for x in diff)
        for _ in range(N - 1):
            step_color = []
            for c, s in zip(self.color, step):
                step_color.append(c + s)
            self.setColor(Color(tuple(step_color)), ignore_bright)
            sleep(1 / REFRESH_RATE)
        self.setColor(new_color, ignore_bright)

    def chgPulse(self, color):
        self.dprint('pulsing on {}{}{}'.format(color, color.rgb,
                                               Color('white')))
        color = self.applyBright(color)
        self.led.pulse(fade_in_time=FADE_DURATION,
                       fade_out_time=FADE_DURATION,
                       on_color=color)

    def chgRain(self, _):
        self.dprint('running rainbow')
        freq1, freq2, freq3 = .03, .03, .03
        ph1, ph2, ph3 = 0, 2, 4
        center, width = 128, 127
        #center, width = 230, 25 #for pastels
        length = 200
        while self.stop_thread is not True:
            for i in range(length):
                if self.stop_thread is True:
                    break
                red = sin(freq1 * i + ph1) * width + center
                green = sin(freq2 * i + ph2) * width + center
                blue = sin(freq3 * i + ph3) * width + center
                self.setColor(Color(red, green, blue))
                sleep((1 / REFRESH_RATE) * 2)

    def autoDimming(self):
        last_dimmed_day = 0
        last_undimmed_day = 0
        while True:
            dt = datetime.now()
            if (last_dimmed_day !=
                    dt.day) and (DIM_START_HOUR <= dt.hour <
                                 DIM_END_HOUR) and self.bright != 0.25:
                self.dprint('auto-dimming')
                last_dimmed_day = dt.day
                self.bright = 0.25
            elif (last_undimmed_day != dt.day) and (
                    dt.hour < DIM_START_HOUR
                    or dt.hour >= DIM_END_HOUR) and self.bright != 1:
                self.dprint('auto-undimming')
                last_undimmed_day = dt.day
                self.bright = 1
            else:
                sleep(60)
                continue

            if self.led.is_lit:
                self.killThread()
                if self.change_type == LightChanges.transition:
                    self.chgTrans(applyBright(self.color),
                                  ignore_bright=True,
                                  duration=3)
                else:
                    self.changeLights(self.change_type, self.color)
            sleep(60)

    def killThread(self):
        if self.thread.is_alive() is not True:
            return
        self.dprint('stop thread')
        self.stop_thread = True
        self.thread.join()
        self.stop_thread = False

    def dprint(self, text):
        if self.verbose:
            print(text)
Example #5
0
# control buttons
#TODO: possible support for multiple light racks in future?
apply = Button(21)
kill = Button(20)

print("PROGRAM ACTIVE")

red.off()
green.off()
blue.off()

selectionLED.color = (0, 0, 0)

while kill.is_pressed == False:  #TODO: add in support for lightRelays1
    selectionLED.pulse(1, 1, (0, 0, 1))  #blue
    blue.on()
    apply.wait_for_press()
    selectionLED.off()
    blue.off()
    apply.wait_for_release()

    selectionLED.pulse(1, 1, (0, 1, 0))  #green
    green.on()
    apply.wait_for_press()
    selectionLED.off()
    green.off()
    apply.wait_for_release()

    selectionLED.pulse(1, 1, (0, 1, 1))  #teal
    green.on()
Example #6
0
class AlertHarness:
    def __init__(self, args):
        if args.test or args.replay:
            self.radio = None
        else:
            r = self.radio = rf95.RF95(cs=RF95_SPI_CS, int_pin=RF95_IRQ_PIN, reset_pin=RF95_RESET_PIN)
            assert r.init(), "failed to intialize radio"
            r.set_modem_config(rf95.Bw125Cr45Sf128)
            r.set_frequency(RF95_FREQ)

        self._args = args

        self.log_handle = open(args.log, 'w') if args.log else None
        self.replay_handle = open(args.replay, 'r') if args.replay else None
        self._pending_line = None
        self._time_offset = 0

        if self.replay_handle:
            if self.read_replay_line():
                self._time_offset = time.time() - self._pending_line[0]

        self.test = args.test
        self.use_tts = args.tts
        self.use_alarm = args.alarm
        self.numbers = args.phone
        self.emails = args.email

        self.stopping = False
        self.led = RGBLED(*RGBLED_PINS)

        self.lcd_thread = LCDThread(SEGMENT_PINS, DIGIT_PINS)

        self.trouble_tags = set()
        self.known_tags = set()

        self.monitor_thread = BackgroundThread(self.status_loop, start=False)
        self.announce_thread = None
        self._buzzer = False

        if twilio is not None:
            self.twilio_client = TwilioClient(TWILIO_SID, TWILIO_AUTH)
        else:
            self.twilio_client = None

        if sendgrid is not None:
            self.mail_client = sendgrid.SendGridAPIClient(apikey=SENDGRID_API_KEY)
        else:
            self.mail_client = None

        self.conn = None
        self.states = StateTracker()

    def read_replay_line(self) -> bool:
        try:
            line = next(self.replay_handle)
            ts, rssi, pkt_hex = line.split(",")
            ts = float(ts.strip())
            rssi = float(rssi.strip())
            pkt = bytes.fromhex(pkt_hex.strip())
            self._pending_line = ts, rssi, pkt
            return True
        except (StopIteration, ValueError):
            self._pending_line = None
            return False

    def set_plotter(self, address: str, port: int = PLT_DEFAULT_PORT):
        if isinstance(port, str):
            port = int(port)
        elif port is None:
            port = PLT_DEFAULT_PORT

        self.conn = mpClient((address, port))

    def send_sms(self, body: str):
        if self.twilio_client is None or not self.numbers:
            return False

        ret = []
        for number in self.numbers:
            msg = self.twilio_client.messages.create(to=number, from_=TWILIO_NUMBER, body=body)
            ret.append(msg)

        return ret

    def send_email(self, subject: str, body: str):
        if self.mail_client is None or not self.emails:
            return False

        personalization = Personalization()

        for email in self.emails:
            email = Email(email)
            personalization.add_to(email)

        from_email = Email(SENDGRID_FROM_ADDRESS)
        content = Content("text/plain", body)
        mail = Mail(from_email, subject, None, content)
        mail.add_personalization(personalization)
        return self.mail_client.client.mail.send.post(request_body=mail.get())

    def get_packet(self, timeout=None) -> Optional[RadioPacket]:
        packet = None

        if self.test:
            return
        elif self.replay_handle:
            packet = self.replay_packet(timeout)
        elif self.radio:
            start = time.time()

            while not self.radio.available():
                sleep(0.005)
                if timeout and (time.time() - start > timeout):
                    return

            rxbuf = self.radio.recv()
            rxbuf = bytes(rxbuf[4:])  # skip flag
            rssi = self.radio.last_rssi

            try:
                packet = RadioPacket.from_bytes(rxbuf, rssi, timestamp=time.time())
            except Exception as e:
                h = rxbuf.hex()
                hexstr = ' '.join(h[x:x + 2] for x in range(0, len(h), 2))
                new_e = RuntimeError("error parsing packet with length %d and data:\n%s"
                                     % (len(rxbuf), hexstr))
                raise new_e from e

        if packet:
            self.states.update(packet)
            return packet

    def replay_packet(self, timeout=None):
        if self._pending_line:
            target = self._pending_line[0] + self._time_offset
            sleep_for = target - time.time()

            if timeout and sleep_for > timeout:
                sleep(timeout)
                return None
            else:
                sleep(max(0, sleep_for))
                timestamp, rssi, rxbuf = self._pending_line
                timestamp = target

                if not self.read_replay_line():
                    print("end of log, stopping")
                    self.stopping = True

                return RadioPacket.from_bytes(rxbuf, rssi, timestamp=timestamp)

    def run_test(self):
        print("Test mode: will simulate an alert in 10 seconds")
        sleep(10)
        self.show_alert(42)
        print("Test mode: returning to normal in 10 seconds")
        sleep(10)
        self.clear_alert()
        print("Test mode: will exit in 5 seconds")
        sleep(5)

    def run(self):
        # Initialize everything as OK
        self.clear_alert()
        self.monitor_thread.start()
        self.lcd_thread.start()

        if self.test:
            return self.run_test()

        while not self.stopping:
            try:
                packet = self.get_packet(timeout=1)

                if not packet:
                    continue

                if self.conn:
                    self.conn.send((packet.raw, packet.rssi, packet.timestamp))

                if self.log_handle:
                    line = '%s,%s,%s' % (packet.timestamp, packet.rssi, packet.raw.hex())
                    self.log_handle.write(line + '\n')

                # print(packet.serial, packet.seq, packet.orientation, packet.rssi, packet.vbatt)
                # pprint(packet.samples[-1])

                self.known_tags.add(packet.tag)

                if self.states.state_for(packet.tag) is State.DISTRESS:
                    if packet.tag not in self.trouble_tags:
                        self.trouble_tags.add(packet.tag)
                        self.show_alert(packet.tag)
                elif packet.tag in self.trouble_tags:
                    self.trouble_tags.remove(packet.tag)
                    self.clear_alert()

            except Exception:
                traceback.print_exc()

    def status_loop(self):
        while not self.stopping:
            for i in range(int(ACTIVE_SLEEP / 0.01)):
                sleep(0.01)

                if self.stopping:
                    break

            tag_strs = ['%d: %s' % (t, self.states.state_for(t).name.lower())
                        for t in self.known_tags]
            print("Active tags:\n%s" % ('\n'.join(tag_strs) or '(none)'))

    def show_alert(self, tag: int):
        print("showing alert for tag", tag)
        self.lcd_thread.set_value(tag)
        self.led.pulse(on_color=RED)

        msg = "Tag %s is in distress!" % tag
        self.announce_msg = msg
        self.announce()

        self.send_email("Bovine Intervention alert", msg)
        self.send_sms("Bovine Intervention alert: " + msg)

    def clear_alert(self):
        print("clearing alert")
        self.led.blink(on_color=GREEN, on_time=0.05, off_time=5 - 0.05)
        self.lcd_thread.clear()
        self.announce_msg = None

        if self.announce_thread:
            self.announce_thread.stop()  # block

    def announce_cb(self, result):
        if self.announce_msg is None or self.stopping:
            # reset to None
            self.announce_thread = None
            self._buzzer = False
        elif self._buzzer:
            self._buzzer = False
            self.announce_thread = CommandThread([TTS_SCRIPT, self.announce_msg], self.announce_cb)
        else:
            self._buzzer = True
            self.announce_thread = CommandThread(["mplayer", "-really-quiet", ALARM_SOUND], self.announce_cb)

    def announce(self):
        if self.announce_thread:
            self.announce_thread.join()  # block

        self.announce_thread = CommandThread(["mplayer", ALARM_SOUND], self.announce_cb)
        self._buzzer = True

    def shutdown(self):
        self.stopping = True
        self.lcd_thread.stop()
        self.monitor_thread.join()
        self.led.close()
        #GPIO.cleanup()

        if self.announce_thread:
            self.announce_thread.stop()

        if self.radio:
            self.radio.cleanup()

        if self.log_handle:
            self.log_handle.close()

        if self.replay_handle:
            self.replay_handle.close()
Example #7
0
class ILedStrip(object):
    """
    Interface to GPIOZERO RGBLED
    Adds support for Hex and Generic words such as:

    "none", "red", "green", "blue", "purple", "yellow"
    "aqua", "orange", "magenta", "white"


    """
    def __init__(self, red, green, blue):
        """
        sets up the Interface

        Args:
            red (int):   GPIO Pin
            green (int): GPIO pin
            blue (int):  GPIO Pin
        """
        self._led_strip = RGBLED(red, green, blue)
        self._cur_color = "#0000FF"
        self._prev_color = "#0000FF"

        self._is_pulse = False

        self._defined_colors = {
            "none": "#000000",
            "red": "#FF0000",
            "green": "#00FF00",
            "blue": "#0000FF",
            "purple": "#FF00FF",
            "yellow": "#FFFF00",
            "aqua": "#00FFFF",
            "orange": "#FF1000",
            "magenta": "#FF0080",
            "white": "#FFFFFF"
        }

    # Setter
    def set_on(self):
        """
        Turns RGB on sets to the defined color
        """
        self._is_pulse = False
        self._led_strip.color = self._cvt_hex(self._cur_color)

    # Setter
    def set_off(self):
        """
        Turns RGB off
        """
        self._is_pulse = False
        self._led_strip.off()

    # Setter
    def set_color_hex(self, color="#000000"):
        """
        Sets the color to hex or sets it to none if not valid hex
        """
        if self._is_valid_hex(color):
            self._led_strip.color = self._cvt_hex(color)
            self._prev_color = self._cur_color
            self._is_pulse = False
            self._cur_color = color

    # Setter
    def set_color_word(self, color="none"):
        """
        Set color to current word or sets it to none if it is not supported
        """
        self._led_strip.color = self._color_map(color)
        self._prev_color = self._cur_color
        self._is_pulse = False
        self._cur_color = self._color_map(color, return_tuple=False)

    # Getter
    def get_status(self):
        """
        returns if the led_strip is lit
        """
        if self._is_pulse:
            return True

        return self._led_strip.is_lit

    def get_pulse_status(self):
        """
        returns true if currently pulsing
        """
        return self._is_pulse

    def get_prev_color(self):
        """
        returns previous color
        """
        return self._color_map(self._prev_color, return_tuple=False)

    # Getter
    def get_defined_colors(self):
        """
        returns what colors are supported and which color it is currently set to
        """
        defined_colors = {}
        for color in self._defined_colors:
            hex_color = self._color_map(color, return_tuple=False)

            if hex_color == self._cur_color:
                defined_colors[color] = True
            else:
                defined_colors[color] = False

        return defined_colors

    def toggle(self):
        """
        Toggles between off and on
        """
        if not self.led_strip.is_lit:
            self.set_on()
        else:
            self.set_off()

    def pulse(self, fade_in_time=5, fade_out_time=5, off_color=(0, 0, 0)):
        on_color = self._cvt_hex(self._cur_color)
        self._is_pulse = True
        self._led_strip.pulse(fade_in_time=fade_in_time,
                              fade_out_time=fade_out_time,
                              on_color=on_color,
                              off_color=off_color)

    def blue2red(self):
        self._led_strip.pulse(fade_in_time=10,
                              fade_out_time=10,
                              on_color=(1, 0, 0),
                              off_color=(0, 0, 1))

    def _cvt_hex(self, colorInHex):
        """
        TODO: make this more reslient
        """

        try:
            red = float(int(colorInHex[1:3], 16)) / 255
            green = float(int(colorInHex[3:5], 16)) / 255
            blue = float(int(colorInHex[5:], 16)) / 255
            return (red, green, blue)
        except:
            return self._cvt_hex(self._cur_color)
            LOGGER.debug("Exception in cvtHex")

    def _color_map(self, color, return_tuple=True):
        if return_tuple:
            return self._cvt_hex(self._defined_colors.get(color, "#000000"))
        else:
            return self._defined_colors.get(color, "#000000")

    def _is_valid_hex(self, colorInHex):
        _rgbstring = re.compile(r'#[a-fA-F0-9]{6}$')
        return bool(_rgbstring.match(colorInHex))
Example #8
0
class bbrun:
    # BBEnc encryption object
    bbenc = None

    # PN532 Scanner object
    bbsc = None # PN532 object

    #Coffee Maker Database Setup
    DATABASE = r'blackbean.db'
    DATAPATH = r''
    bbdb = None # sqlite object
    
    #TFT Display Setup - ST7789 Adafruit 240x240 1.54" SPI
    PIN_DC = 24 
    PIN_RST = 23
    SPI_PORT = 0
    SPI_DEVICE = 0
    disp = None

    # Solid State Relay Setup - Omron
    PIN_RELAY = 26
    relay = None
    
    # RGB LED Setup - Note CA LED: values reversed, led.On() turns OFF led
    PIN_RED   = 5
    PIN_GREEN = 6
    PIN_BLUE  = 4
    C_GREEN = (1,0.5,1)
    C_TEAL  = (1,0.8,0.5)
    T_PULSE = 0.5
    led = None

    # Last scan array - to be used by functions in bbrun
    lastscan = None

    def __init__(self):
    	self.led = RGBLED(self.PIN_RED, self.PIN_GREEN, self.PIN_BLUE)
        self.led.value = (1,1,0)

    	self.relay = LED(self.PIN_RELAY)
    
    	# Create TFT LCD display class.
    	self.disp = TFT.ST7789(self.PIN_DC, rst=self.PIN_RST, \
                            spi=SPI.SpiDev(self.SPI_PORT, self.SPI_DEVICE, \
                                           max_speed_hz=64000000))
    	# Initialize display.
    	self.disp.begin()
    	# Clear the display to a red background.
    	# Can pass any tuple of blue, green, red values (from 0 to 255 each).
    	self.disp.clear((255, 0, 0))
    
        # Initialize blackbean database class
        self.bbdb = bbsql.bbdb(self.DATAPATH, self.DATABASE)

        # Initialize PN532 RFID class
        self.bbsc = bbscan.bbscan()
        print(self.bbsc.resp)

        # Initialize encryption class
        self.bbenc = bbenc.bbenc()
        self.bbenc.load_public()
        print(self.bbenc.resp)

    def LedDemo(self):
    	self.led.pulse(self.T_PULSE, self.T_PULSE, self.C_TEAL, self.C_GREEN)
    	sleep(10)
    
    def RelayDemo(self):
    	self.relay.blink(1)
    	sleep(10)
    	
    def TftDemo(self):
    	# Get a PIL Draw object to start drawing on the display buffer.
    	draw = self.disp.draw()
    
    	# Draw a cyan triangle with a black outline.
    	draw.polygon(   [(10, 275), (110, 240), (110, 310)], outline=(0,0,0), \
                        fill=(0,255,255))
    
    	# Load default font.
    	font = ImageFont.load_default()	
    	
    	# Write two lines of white text on the buffer, rotated 90 degrees counter clockwise.
    	self.DrawRotatedText(self.disp.buffer, 'Hello World!', (150, 120), \
                            90, font, fill=(255,255,255))
    	self.DrawRotatedText(self.disp.buffer, 'This is a line of text.', \
                            (170, 90), 90, font, fill=(255,255,255))
    
    	# Write buffer to display hardware, must be called to make things visible on the
    	# display!
    	self.disp.display()	
    
    def RelayOn(self):
    	self.relay.on()
    
    def RelayOff(self):
    	self.relay.off()
    
    def LedColor(self, rgb=(1,1,1)):
    	self.led.value = rgb
    
    # Define a function to create rotated text.  Unfortunately PIL doesn't have good
    # native support for rotated fonts, but this function can be used to make a
    # text image and rotate it so it's easy to paste in the buffer.
    def DrawRotatedText(self, image, text, position, angle, font, \
                          fill=(255,255,255)):
        # Get rendered font width and height.
        draw = ImageDraw.Draw(image)
        width, height = draw.textsize(text, font=font)
        # Create a new image with transparent background to store the text.
        textimage = Image.new('RGBA', (width, height), (0,0,0,0))
        # Render the text.
        textdraw = ImageDraw.Draw(textimage)
        textdraw.text((0,0), text, font=font, fill=fill)
        # Rotate the text image.
        rotated = textimage.rotate(angle, expand=1)
        # Paste the text into the image, using it as a mask for transparency.
        image.paste(rotated, position, rotated)

    # Display Fortune
    def DrawFortune(self, fortune):
        font = ImageFont.truetype('Momt___.ttf',22)
        angle = 0
        self.disp.buffer.paste((0,0,0), (0,0,240,240))
        length = len(fortune) # number of characters
        CHARLINEMAX = 16
        LINEMAX = 10
        LINESPACE = 20
        XSTART = 10
        YSTART = 10
        FILL = (255,255,255)
        lines = textwrap.wrap(fortune, CHARLINEMAX, break_long_words=False)
        x = XSTART
        y = YSTART
        for line in lines:
            self.DrawRotatedText( \
                self.disp.buffer, line, (x,y), angle, font, fill=FILL)
            y = y + LINESPACE
        self.disp.display()

    # Display Image
    def DisplayImage(self, dirname, imagename):
        image = Image.open(dirname+"/"+imagename) #assume 240x240
        self.disp.display(image) # assume angle 0

    # Display Homescreen
    def DrawHome(self):
        font = ImageFont.truetype('Play With Fire.ttf',42)
        fonttwo = ImageFont.truetype('Momt___.ttf',22)
        angle = 0
        self.disp.buffer.paste((0,0,0), (0, 0, 240, 240))
        self.DrawRotatedText( \
                self.disp.buffer, 'Coffee', (10, 10), angle, font, fill=(255,255,255))
        self.DrawRotatedText(\
                self.disp.buffer, 'Club', (10, 70), angle, font, fill=(255,255,255))
        self.DrawRotatedText(\
                self.disp.buffer, 'Scan Badge', (10, 180), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, 'Get Coffee', (10, 200), angle, fonttwo, fill=(230,230,230))
        self.disp.display()

    # Display Brewscreen
    def DrawBrew(self):
        font = ImageFont.truetype('Play With Fire.ttf',42)
        fonttwo = ImageFont.truetype('Momt___.ttf',22)
        angle = 0
        self.disp.buffer.paste((0,0,0), (0, 0, 240, 240))
        self.DrawRotatedText( \
                self.disp.buffer, 'Brewing', (10, 10), angle, font, fill=(0,255,0))
        self.DrawRotatedText(\
                self.disp.buffer, 'Yum yum!', (10, 90), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, 'Issues?', (10, 130), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, 'Check help sheet', (10, 150), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, 'or contact Chris', (10, 170), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, 'Wallace', (10, 190), angle, fonttwo, fill=(230,230,230))
        self.disp.display()

    # Display Deniedscreen
    def DrawDenied(self):
        font = ImageFont.truetype('Play With Fire.ttf',42)
        fonttwo = ImageFont.truetype('Momt___.ttf',22)
        angle = 0
        self.disp.buffer.paste((0,0,0), (0, 0, 240, 240))
        self.DrawRotatedText( \
                self.disp.buffer, 'Sorry', (10, 10), angle, font, fill=(0,0,255))
        self.DrawRotatedText(\
                self.disp.buffer, 'Badge not', (10, 90), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, 'recognized. To', (10, 110), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, 'join the coffee', (10, 130), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, 'club contact', (10, 150), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, 'Shaun Bowman', (10, 170), angle, fonttwo, fill=(230,230,230))
        self.disp.display()

    # Display Adminscreen
    def DrawAdminIp(self,ipString):
        font = ImageFont.truetype('Play With Fire.ttf',42)
        fonttwo = ImageFont.truetype('MAGIMTOS.ttf',32)
        angle = 0
        self.disp.buffer.paste((50,0,0), (0, 0, 240, 240))
        self.DrawRotatedText( \
            self.disp.buffer, 'IP:', (10, 10), angle, font,
            fill=(200,0,50))
        ipString = ipString.split('.')
        self.DrawRotatedText( \
            self.disp.buffer, ipString[0], (10, 80), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText( \
            self.disp.buffer, ipString[1], (10, 115), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText( \
            self.disp.buffer, ipString[2], (10, 150), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText( \
            self.disp.buffer, ipString[3], (10, 185), angle, fonttwo, fill=(230,230,230))
        self.disp.display()

    # Display Adminscreen
    def DrawAdmin(self):
        font = ImageFont.truetype('Play With Fire.ttf',42)
        fonttwo = ImageFont.truetype('MAGIMTOS.ttf',32)
        angle = 0
        self.disp.buffer.paste((50,0,0), (0, 0, 240, 240))
        self.DrawRotatedText( \
                self.disp.buffer, 'Admin', (10, 10), angle, font,
                             fill=(200,0,50))
        self.DrawRotatedText(\
                self.disp.buffer, '1 Add', (10, 70), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, '2 Remove', (10, 110), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, '3 Stats', (10, 150), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, '4 Exit', (10, 190), angle, fonttwo, fill=(230,230,230))
        self.disp.display()

    # Display Addscreen
    def DrawAdd(self):
        font = ImageFont.truetype('Play With Fire.ttf',42)
        fonttwo = ImageFont.truetype('MAGIMTOS.ttf',32)
        angle = 0
        self.disp.buffer.paste((50,0,0), (0, 0, 240, 240))
        self.DrawRotatedText( \
                self.disp.buffer, 'Admin', (10, 10), angle, font,
                             fill=(200,0,50))
        self.DrawRotatedText(\
                self.disp.buffer, 'scan', (10, 70), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, 'first', (10, 110), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, 'last', (10, 150), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, '4 Exit', (10, 190), angle, fonttwo, fill=(230,230,230))
        self.disp.display()

    # Display Removescreen
    def DrawRemove(self):
        font = ImageFont.truetype('Play With Fire.ttf',42)
        fonttwo = ImageFont.truetype('MAGIMTOS.ttf',32)
        angle = 0
        self.disp.buffer.paste((50,0,0), (0, 0, 240, 240))
        self.DrawRotatedText( \
                self.disp.buffer, 'Admin', (10, 10), angle, font,
                             fill=(200,0,50))
        self.DrawRotatedText(\
                self.disp.buffer, 'first', (10, 70), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, 'last', (10, 110), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, '3 Remove', (10, 150), angle, fonttwo, fill=(230,230,230))
        self.DrawRotatedText(\
                self.disp.buffer, '4 Exit', (10, 190), angle, fonttwo, fill=(230,230,230))
        self.disp.display()

    # Draw Recieved
    def DrawRecieved(self, x, y):
        font = ImageFont.truetype('arrow_7.ttf',42)
        angle = 0
        char = '&'
        self.DrawRotatedText( \
                self.disp.buffer, char, (x, y), angle, font,
                             fill=(200,0,50))
        self.disp.display()

    # Standbye Pulse
    def LedStandby(self):
        T_PULSE = 2
    	self.led.pulse(T_PULSE, T_PULSE, self.C_TEAL, self.C_GREEN)

    # Brew Pulse
    def LedBrew(self):
        T_PULSE = 0.5
        COLOR_ON = (1,0,1)
        COLOR_OFF = (1,1,1)
    	self.led.pulse(T_PULSE, T_PULSE, COLOR_ON, COLOR_OFF)

    # Denied Pulse
    def LedDenied(self):
        T_PULSE = 0.5
        COLOR_ON = (0,1,1)
        COLOR_OFF = (1,1,1)
    	self.led.pulse(T_PULSE, T_PULSE, COLOR_ON, COLOR_OFF)

    # Admin Pulse
    def LedAdmin(self):
        T_PULSE = 0.1
        COLOR_ON = (1,1,0.5)
        COLOR_OFF = (0.5,1,0.5)
    	self.led.pulse(T_PULSE, T_PULSE, COLOR_ON, COLOR_OFF)
Example #9
0
	led2.on()
	led3.on()

	button.wait_for_press()
	button.wait_for_release()

	led1.blink()
	sleep(0.4)
	led2.blink()
	sleep(0.4)
	led3.blink()

	button.wait_for_press()
	button.wait_for_release()
	
	led1.pulse()
	sleep(0.4)
	led2.pulse()
	sleep(0.4)
	led3.pulse()
	
	button.wait_for_press()
	button.wait_for_release()
	
	led1.on()
	led2.color(mode1)
	led3.color(mode2)
	
	button.wait_for_press()
	button.wait_for_release()
	
Example #10
0
class Beacon(object):

    connectState = ConnectState.Disconnected
    failConnectCount = 0
    configData = None
    commandsData = None
    client = None
    soundDir = os.path.join(launchDir, 'sounds/')
    rgbLED = None
    button = None
    buttonHoldTime = None
    persistentLedRule = None

    def __init__(self):
        logging.info("Beacon service initialized")

        with open(os.path.join(launchDir, 'beacon.json')) as data_file:
            self.configData = json.load(data_file)
        #need to account for no json data loaded

        if (self.configData.get("gpio")):
            gpioData = self.configData["gpio"]

            if gpioData.get("button"):
                self.button = Button(int(gpioData["button"]))
                self.button.when_released = self.buttonReleased
                self.button.when_held = self.buttonHeld
            else:
                logging.error(
                    "config json gpio object missing required button id")

            if gpioData.get("red_led") and gpioData.get(
                    "green_led") and gpioData.get("blue_led"):
                self.rgbLED = RGBLED(int(gpioData["red_led"]),
                                     int(gpioData["green_led"]),
                                     int(gpioData["blue_led"]), False,
                                     (0, 0, 0), True)
            else:
                logging.error(
                    "config json gpio object missing required redled, greenled, and blueled ids"
                )

        else:
            logging.error("config json missing require gpio object")

        if self.configData.get("directories"):
            dirObj = self.configData["directories"]
            if dirObj.get("sound"):
                soundDir = dirObj["sound"]

        if self.configData.get("commands"):
            self.commandsData = self.configData["commands"]

        self.ledDisplay(LedDisplayRule(0, 1, 0, 1, 1))
        sleep(1)

        self.client = MQTTClient(self.configData["credentials"]["username"],
                                 self.configData["credentials"]["key"])
        self.client.on_connect = self.connected
        self.client.on_disconnect = self.disconnected
        self.client.on_message = self.message

        while True:
            if self.connectState == ConnectState.Disconnected:
                self.connect()
            elif self.connectState == ConnectState.PendingReconnect:
                self.reconnect()
            try:
                self.client.loop()
            except RuntimeError:
                logging.exception("runtime error caught from mqtt client loop")
                self.reconnect()

    def buttonHeld(self):
        self.buttonHoldTime = time.time()

    def buttonReleased(self):
        if self.buttonHoldTime is not None:
            heldTime = time.time() - self.buttonHoldTime + 1
            self.buttonHoldTime = None
            print heldTime
            if heldTime > 5:
                self.ledDisplay(LedDisplayRule(1, 0, 0, 3, .5))
                sleep(2)
                self.stopLED()
                os.system('sudo shutdown -r now')
        else:
            self.stopLED()
            self.persistentLedRule = None
            print self.commandsData
            if mixer.get_init() and mixer.music.get_busy():
                mixer.music.stop()
                mixer.quit()
            elif self.commandsData is not None:
                self.client.publish(self.configData["feeds"]["outbound"],
                                    self.commandsData[0])

    def message(self, client, feed_id, payload):
        msgStr = 'Feed {0} received new value: {1}'.format(feed_id, payload)
        log_data = ""
        with open(logFilePath, 'r') as myfile:
            log_data = myfile.read().replace('\n', '')
        if log_data.find(msgStr) == -1 or testing:
            logging.info(msgStr)
            messageData = None
            try:
                messageData = json.loads(payload)
            except:
                pass
            sound = None
            volume = 1
            redVal = 0
            greenVal = 1
            blueVal = 0
            blinkCount = 1
            blinkRate = 1
            persistent = False
            pulse = False
            if self.configData.get("sounds"):
                sound = self.configData["sounds"]["default"]
            if messageData is not None:
                if messageData.get("sound"):
                    sound = self.configData["sounds"][messageData["sound"]]
                if messageData.get("persistent") and str(
                        messageData["persistent"]).lower() == "true":
                    persistent = True
                if messageData.get("volume") is not None:
                    volume = float(messageData.get("volume"))
                if messageData.get("blinkCount") is not None:
                    blinkCount = int(messageData.get("blinkCount"))
                if messageData.get("blinkRate") is not None:
                    blinkRate = float(messageData.get("blinkRate"))
                if messageData.get("pulse") is not None and str(
                        messageData["pulse"]).lower() == "true":
                    pulse = True
                if messageData.get("color") is not None:
                    try:
                        colorArr = str(messageData.get("color")).split("/")
                        redVal = float(colorArr[0])
                        greenVal = float(colorArr[1])
                        blueVal = float(colorArr[2])
                    except:
                        pass

            if sound is not None:
                mixer.init()
                mixer.music.set_volume(volume)
                mixer.music.load(self.soundDir + sound)
                mixer.music.play()
            self.ledDisplay(
                LedDisplayRule(redVal, greenVal, blueVal, blinkCount,
                               blinkRate, pulse, persistent))

    def stopLED(self):
        self.rgbLED._stop_blink()
        self.rgbLED.off()

    def ledDisplay(self, rule):
        self.stopLED()
        blinkCount = rule.blinkCount
        if (rule.persistent):
            blinkCount = None
            self.persistentLedRule = rule
        if (rule.pulse):
            self.rgbLED.pulse(fade_in_time=rule.blinkRate,
                              fade_out_time=rule.blinkRate,
                              on_color=(rule.r, rule.g, rule.b),
                              off_color=(0, 0, 0),
                              n=blinkCount,
                              background=True)
        else:
            self.rgbLED.blink(on_time=rule.blinkRate,
                              off_time=rule.blinkRate,
                              fade_in_time=0,
                              fade_out_time=0,
                              on_color=(rule.r, rule.g, rule.b),
                              off_color=(0, 0, 0),
                              n=blinkCount,
                              background=True)

    def connected(self, client):
        logging.info("Connected to Adafruit IO")
        self.connectState = ConnectState.Connected
        self.failConnectCount = 0
        self.client.subscribe(self.configData["feeds"]["inbound"])

    def disconnected(self, client):
        logging.info('Disconnected from AdafruitIO')
        self.connectState = ConnectState.Disconnected
        self.reconnect()

    def connect(self):
        logging.info("init connect to Adafruit IO")
        self.connectState = ConnectState.Connecting
        try:
            self.client.connect()
        except Exception as e:
            logging.exception("Exception from Adafruit client connect")
            self.reconnect()

    def reconnect(self):
        self.failConnectCount += 1
        logging.info('pending Adafruit IO reconnect - failcount=' +
                     str(self.failConnectCount))
        self.connectState = ConnectState.Connecting
        sleep(10)
        self.connect()
Example #11
0
    while 1:

        current_time = datetime.now()

        fsm.process()

        diag.process()

        sleep(TICK_DURATION)

except Exception as e:
    logging.exception("Unhandled exception - '%s'", str(e))

    # Close all previous GPIO devices
    fsm.close()

    # Turn relays off
    hw = DigitalOutputDevice(HW_RELAY_PIN, HW_RELAY_ACTIVE_HIGH)
    ch = DigitalOutputDevice(CH_RELAY_PIN, CH_RELAY_ACTIVE_HIGH)

    hw.off()
    ch.off()

    # Put RGB LED on pulsing red
    rgb_led = RGBLED(RED_LED_PIN,
                     GREEN_LED_PIN,
                     BLUE_LED_PIN,
                     active_high=RGB_ACTIVE_HIGH)

    rgb_led.pulse(1.5, 1.5, on_color=(1, 0, 0))