Beispiel #1
0
class DISTANCE_SENSOR(parlay.ParlayCommandItem):

    TRIG_PIN = parlay.ParlayProperty(val_type=int, default=13)
    ECHO_PIN = parlay.ParlayProperty(val_type=int, default=15)

    DISTANCE = parlay.ParlayDatastream(default=0)
    POLLING = parlay.ParlayProperty(val_type=int, default=0)
    POLLING_INTERVAL = parlay.ParlayProperty(val_type=int, default=1)

    @parlay.parlay_command()
    def init(self):
        GPIO.setmode(GPIO.BOARD)       # Numbers GPIOs by physical location

        GPIO.setup(self.TRIG_PIN, GPIO.OUT)
        GPIO.setup(self.ECHO_PIN, GPIO.IN)


    @parlay.parlay_command()
    def poll(self):
        GPIO.output(self.TRIG_PIN, 0)
        time.sleep(0.000002)  # let it settle

        GPIO.output(self.TRIG_PIN, 1)
        time.sleep(0.00001)  # let it settle
        GPIO.output(self.TRIG_PIN, 0)

        #busy loop. wait for echo pin to go high
        while GPIO.input(self.ECHO_PIN) == 0:
            pass
        time1 = time.time()
        while GPIO.input(self.ECHO_PIN) == 1:
            pass
        time2 = time.time()

        duration = time2 - time1
        self.DISTANCE = duration * 340 / 2 * 100
        return self.DISTANCE

    @parlay.parlay_command()
    def poll_forever(self):
        while True:
            self.poll()
            time.sleep(self.POLLING_INTERVAL)
Beispiel #2
0
class RG_LED(parlay.ParlayCommandItem):

    R_PIN = parlay.ParlayProperty(val_type=int, default=11)
    G_PIN = parlay.ParlayProperty(val_type=int, default=12)

    @parlay.parlay_command()
    def init(self):

        GPIO.setup(self.R_PIN, GPIO.OUT)
        GPIO.output(self.R_PIN, GPIO.HIGH)

        GPIO.setup(self.G_PIN, GPIO.OUT)
        GPIO.output(self.G_PIN, GPIO.HIGH)

        self.p_R = GPIO.PWM(self.R_PIN, 2000)  # set Frequency to 2KHz
        self.p_G = GPIO.PWM(self.G_PIN, 2000)

        self.p_R.start(0)  # Initial duty Cycle = 0(leds off)
        self.p_G.start(0)

    @parlay.parlay_command()
    def turn_green(self):
        self.p_R.ChangeDutyCycle(0)
        self.p_G.ChangeDutyCycle(100)

    @parlay.parlay_command()
    def turn_red(self):
        self.p_G.ChangeDutyCycle(0)
        self.p_R.ChangeDutyCycle(100)

    @parlay.parlay_command()
    def turn_off(self):
        self.p_G.ChangeDutyCycle(0)
        self.p_R.ChangeDutyCycle(0)

    @parlay.parlay_command()
    def blink(self, times):
        for x in range(int(times)):
            self.turn_green()
            sleep(1)
            self.turn_red()
            sleep(1)
Beispiel #3
0
class Adder(parlay.ParlayCommandItem):
    # all of these parameters are optional, but recommended to
    x = parlay.ParlayProperty(default=0, val_type=int)
    y = parlay.ParlayProperty(default=0, val_type=int)
    result = parlay.ParlayDatastream(default=0)

    @parlay.parlay_command()
    def echo(self, text):
        """
        Will Echo whatever was sent to the python console
        """

        print(text)

    @parlay.parlay_command()
    def add(self):
        """
        Will add x and y and then return and echo the result
        """
        self.result = self.x + self.y
        self.echo(self.result)

        return self.result
Beispiel #4
0
class CloudStressTest(parlay.ParlayCommandItem):

    data = parlay.ParlayDatastream(val_type=float, default=0.0)
    sleep_time = parlay.ParlayProperty(val_type=float, default=1)

    @parlay.parlay_command()
    def count_up(self, max):
        """

        :param max:
        :type max int
        :return:
        """
        for x in xrange(max):
            self.data = x
            time.sleep(self.sleep_time)
Beispiel #5
0
class LCD(parlay.ParlayCommandItem):

    TEXT = parlay.ParlayProperty(val_type=str, default="Hello World")

    @parlay.parlay_command()
    def init(self):

        LCD1602.init(0x27, 1)  # init(slave address, background light)
        LCD1602.write(0, 0, 'Hello')
        LCD1602.write(1, 1, 'World')
        time.sleep(1)
        LCD1602.clear()

    @parlay.parlay_command()
    def loop(self):
        current_text = ""
        while True:
            "Scroll Text"
            # add whitespace
            if len(self.TEXT) > 16:
                text = self.TEXT
                # fancy scrolling if we have a long string
                for i in range(len(text)):
                    #break if text changes
                    if text != self.TEXT:
                        break
                    LCD1602.write(0, 0, text)
                    text = text[1:]
                    time.sleep(0.5)
                    LCD1602.clear()
            elif current_text != self.TEXT:
                #static change
                LCD1602.clear()
                LCD1602.write(0, 0, self.TEXT)
                current_text = self.TEXT
                time.sleep(1)  # hold for at least 1 second
            else:  # sleep poll
                time.sleep(1)
Beispiel #6
0
class CloudLink(parlay.ParlayCommandItem):

    connected_to_cloud = parlay.ParlayProperty(val_type=bool,
                                               default=False,
                                               read_only=True)
    base_link_uri = parlay.ParlayProperty(
        val_type=str,
        default=CloudLinkSettings.CLOUD_SERVER_ADDRESS + "/channels")
    device_registration_uri = parlay.ParlayProperty(
        val_type=str,
        default=CloudLinkSettings.CLOUD_SERVER_ADDRESS +
        "/device_stats/api/v1/device")
    uuid = parlay.ParlayProperty(val_type=str)

    def __init__(self):
        parlay.ParlayCommandItem.__init__(self, "parlay.items.cloud_link",
                                          "Cloud Link")
        self._http_agent = Agent(self._reactor)
        self.channel_uri = None
        self.cloud_factory = None

        if CloudLinkSettings.PRIVATE_KEY_LOCATION is None:
            raise RuntimeError(
                "CloudLinkSettings.PRIVATE_KEY_LOCATION must be set for cloud to work"
            )

        if CloudLinkSettings.UUID_LOCATION is None:
            raise RuntimeError(
                "CloudLinkSettings.UUID_LOCATION must be set for cloud to work"
            )

        try:
            with open(CloudLinkSettings.UUID_LOCATION, 'r') as uuid_file:
                self.uuid = uuid_file.read()

        except IOError:
            logger.warn(
                "Error reading UUID file. Has this device been registered?")
            self.uuid = ""

    @parlay.parlay_command(async=True)
    def get_public_key(self):
        if CloudLinkSettings.PUBLIC_KEY_LOCATION is None:
            raise Exception(
                "Public Key Location not Set. Please set CloudLinkSettings.PUBLIC_KEY_LOCATION"
            )
        # simply open and read it
        with open(CloudLinkSettings.PUBLIC_KEY_LOCATION) as public_key_file:
            return public_key_file.read()

    @parlay.parlay_command(async=True)
    def generate_keys(self):
        private_key = rsa.generate_private_key(public_exponent=65537,
                                               key_size=2048,
                                               backend=default_backend())

        private_pem = private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.BestAvailableEncryption(
                bytes(CloudLinkSettings.PRIVATE_KEY_PASSPHRASE)))
        public_pem = private_key.public_key().public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo)
        with open(CloudLinkSettings.PRIVATE_KEY_LOCATION, 'w') as key_file:
            key_file.write(str(private_pem))

        with open(CloudLinkSettings.PUBLIC_KEY_LOCATION, 'w') as key_file:
            key_file.write(str(public_pem))

    @parlay.parlay_command()
    def register_device_with_cloud(self, username, password, name, serial,
                                   group_id, notes):
        """
        Register the public and private keys with the cloud.
        If you already have them registered this will overwrite them
        :param username: username of a user with access to the cloud
        :param password: password of the user to authenticate with
        :param name: the name of the device
        :param serial:  the serial number of the device
        :param group_id:  the id given to the access group for this device
        :type group_id int
        :param notes: any notes to attach to this device
        :return: the UUID of the newly created device
        """
        result = requests.post(self.device_registration_uri,
                               data={
                                   'name': name,
                                   'serial': serial,
                                   'group': group_id,
                                   'notes': notes,
                                   "public_key": self.get_public_key()
                               },
                               auth=(username, password))

        if result.ok:
            self.uuid = result.json()["UUID"]
            with open(CloudLinkSettings.UUID_LOCATION, 'w+') as uuid_file:
                uuid_file.write(self.uuid)

            return self.uuid
        else:
            raise RuntimeError("Error registering device: " +
                               str(result.status_code) + " - " + result.text)

    @parlay.parlay_command(async=True)
    def http_request(self, path="/", encode='zlib'):
        """
        Do an http request on the broker
        :type path str
        """
        url = "http://localhost:" + str(Broker.get_instance().http_port) + path
        print url
        # http"://localhost:broker.http_port
        request = self._http_agent.request(
            'GET', url, Headers({'User-Agent': ['Twisted Web Client']}), None)
        request.addCallback(lambda response: readBody(response))
        request.addCallback(lambda html: (base64.b64encode(html.encode(encode))
                                          ) if encode == "zlib" else html)
        return request

    @parlay.parlay_command(async=True)
    def connect_to_cloud_channel(self):
        """
        Connect up to the cloud channel with UUID uuid
        :param uuid: the UUID of this device. The uuid determines which channel you are connected to
        :return:
        """
        if self.uuid is None or self.uuid == "":
            raise RuntimeError(
                "Must have a valid UUID to connect to the cloud")

        if self.connected_to_cloud:
            raise RuntimeError("Already Connected to cloud")

        yield self.get_channel()
        # cool, now set up the websocket connection to that channel
        reactor = self._adapter.reactor

        print "attempting to connect to", self.channel_uri
        self.cloud_factory = CloudLinkWebsocketClientFactory(self,
                                                             self.channel_uri,
                                                             reactor=reactor)
        self.cloud_factory.protocol = CloudLinkWebsocketClient
        self.cloud_factory.continueTrying = True  # attempt to reconnect

        if self.channel_uri.startswith("wss"):
            reactor.connectSSL(self.cloud_factory.host,
                               self.cloud_factory.port, self.cloud_factory,
                               ssl.ClientContextFactory())
        else:
            reactor.connectTCP(self.cloud_factory.host,
                               self.cloud_factory.port, self.cloud_factory)

    @run_in_thread
    def get_channel(self):
        #first get a token we need to sign in order to prove we are who we say we are
        r = requests.get(str(self.base_link_uri) + "/get_device_token",
                         params={
                             "UUID": self.uuid,
                         })

        token = r.json()["token"]
        # get the private Key
        with open(CloudLinkSettings.PRIVATE_KEY_LOCATION, 'r') as key_file:
            private_key = serialization.load_pem_private_key(
                key_file.read(),
                password=CloudLinkSettings.PRIVATE_KEY_PASSPHRASE,
                backend=default_backend())

        # sign the token with our private key
        signer = private_key.signer(padding.PKCS1v15(), hashes.SHA256())
        signer.update(bytes(token))
        signature = signer.finalize()

        # get the randomly assigned channel for my UUID
        r = requests.get(str(self.base_link_uri) + "/get_device_group",
                         params={
                             "UUID": self.uuid,
                             "signature": b64encode(signature),
                             "format": "PKCS1_v1_5"
                         })
        if r.ok:
            self.channel_uri = r.json()["channel"]
        elif r.status_code == 400:
            raise Exception("UUID or Token not registered with Cloud.")
        elif r.status_code == 403:
            raise Exception(
                "Signature didn't verify correctly. Bad private key or signature."
            )

    @parlay.parlay_command(async=True)
    def disconnect_from_cloud(self):
        self.cloud_factory.continueTrying = False  # stop retrying
        self.cloud_factory.disconnect()