Beispiel #1
0
def metars(source, key="xml"):
    """Parse METAR information retrieved from https://aviationweather.gov/metar.

    Parameters
    ----------
    source: :ref:`Record generator <record-generators>` returning records containing XML data, required
    key: :ref:`Record key <record-keys>`, optional

    Yields
    ------
    records: dict
        Records will contain METAR data extracted from XML.
    """

    for record in source:
        response = record[key]
        for data in response.findall("data"):
            for metar in sorted(data.findall("METAR"),
                                key=lambda x: x.find("observation_time").text):
                output = dict()
                for element in metar.findall("raw_text"):
                    add_field(output, "raw", element.text)
                for element in metar.findall("station_id"):
                    add_field(output, "station-id", element.text)
                for element in metar.findall("observation_time"):
                    add_field(output, "observation-time",
                              arrow.get(element.text))
                for element in metar.findall("latitude"):
                    add_field(output, "latitude",
                              quantity(float(element.text), units.degrees))
                for element in metar.findall("longitude"):
                    add_field(output, "longitude",
                              quantity(float(element.text), units.degrees))
                for element in metar.findall("temp_c"):
                    add_field(output, "temperature",
                              quantity(float(element.text), units.degC))
                for element in metar.findall("depoint_c"):
                    add_field(output, "dewpoint",
                              quantity(float(element.text), units.degC))
                for element in metar.findall("wind_dir_degrees"):
                    add_field(output, "wind-direction",
                              quantity(float(element.text), units.degrees))
                for element in metar.findall("wind_speed_kt"):
                    add_field(
                        output, "wind-speed",
                        quantity(float(element.text),
                                 units.nautical_miles_per_hour))
                for element in metar.findall("visibility_statute_mi"):
                    add_field(output, "visibility",
                              quantity(float(element.text), units.mile))
                for element in metar.findall("altim_in_hg"):
                    add_field(output, "altimeter",
                              quantity(float(element.text), units.inHg))
                for element in metar.findall("flight_category"):
                    add_field(output, "flight-category", element.text)
                for element in metar.findall("elevation_m"):
                    add_field(output, "elevation",
                              quantity(float(element.text), units.meters))
                yield output
Beispiel #2
0
def ios(rate=quantity(1, units.second)):
    """Retrieve motion information from an iOS device.

    This component requires the `motion` module provided by Pythonista.

    Parameters
    ----------
    rate: time quantity, required
        Rate at which motion data will be retrieved.

    Yields
    ------
    records: dict
        Records will contain information including the current acceleration due to gravity and the user, along with device attitude.
    """

    import time
    import motion # pylint: disable=import-error

    rate = rate.to(units.seconds).magnitude

    motion.start_updates()

    try:
        while True:
            gravity = quantity(motion.get_gravity(), units.meters * units.seconds * units.seconds)
            acceleration = quantity(motion.get_user_acceleration(), units.meters * units.seconds * units.seconds)
            attitude = quantity(motion.get_attitude(), units.radians)

            record = dict()
            add_field(record, ("gravity", "x"), gravity[0])
            add_field(record, ("gravity", "y"), gravity[1])
            add_field(record, ("gravity", "z"), gravity[2])

            add_field(record, ("acceleration", "x"), acceleration[0])
            add_field(record, ("acceleration", "y"), acceleration[1])
            add_field(record, ("acceleration", "z"), acceleration[2])

            add_field(record, ("attitude", "roll"), attitude[0])
            add_field(record, ("attitude", "pitch"), attitude[1])
            add_field(record, ("attitude", "yaw"), attitude[2])

            yield record

            time.sleep(rate)

    except GeneratorExit:
        motion.stop_updates()
Beispiel #3
0
def metronome(rate=pipecat.quantity(1.0, pipecat.units.seconds)):
    """Generate an empty record at fixed time intervals using the host clock.

    Typically, you would use functions such as
    :func:`pipecat.utility.add_field` or :func:`pipecat.utility.add_timestamp`
    to populate the (otherwise empty) records.

    Examples
    --------

    If you want to know what time it is, at 5-minute intervals:

    >>> pipe = pipecat.device.clock.metronome(pipecat.quantity(5, pipecat.units.minutes))
    >>> pipe = pipecat.utility.add_timestamp(pipe)
    >>> for record in pipe:
    ...   print record

    Parameters
    ----------
    rate: time quantity, required
        The amount of time to wait between records.

    Yields
    ------
    record: dict
        Empty record returned at fixed time intervals.
    """
    delay = rate.to(pipecat.units.seconds).magnitude
    last_time = time.time()
    while True:
        yield dict()
        next_time = last_time + delay
        time.sleep(next_time - time.time())
        last_time = next_time
 def __getitem__(self, key):
     values = self._columns[key]
     if isinstance(values[0], pipecat.quantity):
         values = pipecat.quantity(
             numpy.array([value.magnitude for value in values]),
             values[0].units)
     else:
         values = numpy.array(values)
     return values
Beispiel #5
0
def obd(connection, commands=None, rate=quantity(5, units.second)):
    """Retrieve OBD-II data from an automobile.

    This component requires the `Python-OBD` module (http://python-obd.readthedocs.io).

    Parameters
    ----------
    connection: :class:`obd.OBD` instance, required.
    rate: time quantity, required
        Rate at which data will be retrieved.

    Yields
    ------
    record: dict
        Records will contain OBD-II data retrieved from an automobile computer.
    """

    # Caller must supply an obd.OBD instance that's already connected.
    if not (isinstance(connection, obdii.OBD) and connection.is_connected()):
        raise ValueError("A valid obd.OBD connection is required.")

    # Get the set of available commands.
    if commands is None:
        commands = []
        for command in connection.supported_commands:
            try:
                if command.mode not in [1]:
                    continue
                if command.pid in [0x00, 0x01, 0x02, 0x20, 0x40, 0x41]:
                    continue
                commands.append(command)
            except: # pylint: disable=bare-except
                pass

    rate = rate.to(units.seconds).magnitude

    while True:
        record = dict()
        for command in commands:
            sys.stdout.flush()
            try:
                response = connection.query(command)
                name = command.name.lower().replace("_", "-")
                add_field(record, name, response.value)
            except: # pylint: disable=bare-except
                pass

        yield record

        time.sleep(rate)
Beispiel #6
0
def icharger208b(source):
    """Parse data from an iCharger 208B battery charger.

    Parses data events emitted by the charger during charge, discharge, etc.
    Likely works with other models from iCharger, but this is untested.
    Consider :ref:`contributing` to let us know.

    This model battery charger comes with a USB cable that provides
    serial-over-USB communication with the host computer.  To connect with the
    charger, you'll need to open a handle to the appropriate serial port, the
    name of which will vary between platforms and based on the number of
    devices currently connected, and feed lines of text to the parser.

    Examples
    --------

    Open a serial port on a Mac OSX computer using `pySerial <http://pyserial.readthedocs.io>`_, read lines from the serial port,
    parse them into records, and print them to stdout:

    >>> pipe = serial.serial_for_url("/dev/cu.SLAB_USBtoUART", baudrate=128000)
    >>> pipe = pipecat.utility.readline(pipe)
    >>> pipe = pipecat.device.charger.icharger208b(pipe)
    >>> for record in pipe:
    ...   print record

    Parameters
    ----------
    source: :ref:`Record generator <record-generators>` returning records containing a "string" field.

    Yields
    ------
    records: dict
        Records will contain information including the charge mode, supply
        voltage, battery voltage, battery current, internal and external
        charger temperature, and the total charged added-to / removed-from the
        battery.
    """

    modes = {
        1: "charge",
        2: "discharge",
        3: "monitor",
        4: "wait",
        5: "motor",
        6: "finished",
        7: "error",
        8: "trickle-LIxx",
        9: "trickle-NIxx",
        10: "foam-cut",
        11: "info",
        12: "discharge-external",
    }

    for record in source:
        raw = record["string"].strip().split(";")

        record = dict()
        add_field(record, ("charger", "mode"), modes[int(raw[1])])
        add_field(record, ("charger", "supply"),
                  quantity(float(raw[3]) / 1000, units.volts))
        add_field(record, ("battery", "voltage"),
                  quantity(float(raw[4]) / 1000, units.volts))
        add_field(record, ("battery", "cell1", "voltage"),
                  quantity(float(raw[6]) / 1000, units.volts))
        add_field(record, ("battery", "cell2", "voltage"),
                  quantity(float(raw[7]) / 1000, units.volts))
        add_field(record, ("battery", "cell3", "voltage"),
                  quantity(float(raw[8]) / 1000, units.volts))
        add_field(record, ("battery", "cell4", "voltage"),
                  quantity(float(raw[9]) / 1000, units.volts))
        add_field(record, ("battery", "cell5", "voltage"),
                  quantity(float(raw[10]) / 1000, units.volts))
        add_field(record, ("battery", "cell6", "voltage"),
                  quantity(float(raw[11]) / 1000, units.volts))
        add_field(record, ("battery", "cell7", "voltage"),
                  quantity(float(raw[12]) / 1000, units.volts))
        add_field(record, ("battery", "cell8", "voltage"),
                  quantity(float(raw[13]) / 1000, units.volts))
        add_field(record, ("battery", "current"),
                  quantity(float(raw[5]) * 10, units.milliamps))
        add_field(record, ("charger", "temperature", "internal"),
                  quantity(float(raw[14]) / 10, units.degC))
        add_field(record, ("charger", "temperature", "external"),
                  quantity(float(raw[15]) / 10, units.degC))
        add_field(record, ("battery", "charge"),
                  quantity(float(raw[16]), units.milliamps * units.hours))

        yield record