コード例 #1
0
    def test_call_from_other_module(self):
        event = Event('other_event')
        event._module = 'other_module'

        with pytest.raises(Exception) as ex:
            event.increment()
コード例 #2
0
import math
from enum import Enum
from io import BytesIO
from typing import Any, Dict, List

from util.detail import LOGGER
from util.event_stats import Event
from main_window.data_entry_id import DataEntryIds, DataEntryValues
from main_window.packet_parser import PacketParser, Header

BULK_SENSOR_EVENT = Event('bulk_sensor')

# Aggregated DataEntryIds for iteration. Outside function for access by tests
SENSOR_TYPES = [DataEntryIds.BAROMETER, DataEntryIds.GPS, DataEntryIds.ACCELEROMETER, DataEntryIds.IMU, DataEntryIds.TEMPERATURE, DataEntryIds.VOLTAGE]
OTHER_STATUS_TYPES = [DataEntryIds.DROGUE_IGNITER_CONTINUITY, DataEntryIds.MAIN_IGNITER_CONTINUITY, DataEntryIds.FILE_OPEN_SUCCESS]

# Converting bit array status to readable values
BITARRAY_TO_STATUS = {
    0b00000000: DataEntryValues.STATUS_NOMINAL,
    0b00000001: DataEntryValues.STATUS_NONCRITICAL_FAILURE,
    0b00000011: DataEntryValues.STATUS_CRITICAL_FAILURE,
}

# Parser's subpacket ids, according to spec. NOT DataIds
class SubpacketIds(Enum):
    STATUS_PING = 0x00
    GPS = 0x04
    ORIENTATION = 0x06
    BULK_SENSOR = 0x30

class CompPacketParser(PacketParser):
コード例 #3
0
import util.event_stats as event_stats
from util.event_stats import Event, get_event_stats_snapshot
from time import time
import pytest

TEST_EVENT = Event('test_event')


class TestEventStats:
    def setup_method(self):
        """ setup any state tied to the execution of the given method in a
        class.  setup_method is invoked for every test method of a class.
        """
        pass

    def teardown_method(self):
        """ teardown any state that was previously setup with a setup_method
        call.
        """
        # Clear stats
        event_stats._stats = dict()

    def test_general_usage(self):
        snapshot = get_event_stats_snapshot()

        TEST_EVENT.increment()

        ret = TEST_EVENT.wait(snapshot)

        assert ret == 1
コード例 #4
0
from typing import Iterable
from enum import Enum, auto
from abc import ABC, abstractmethod
from util.detail import LOGGER
from util.event_stats import Event
from threading import RLock

SENSOR_READ_EVENT = Event('sensor_read')


class SensorType(Enum):
    GPS = auto()
    IMU = auto()
    ACCELEROMETER = auto()
    BAROMETER = auto()
    TEMPERATURE = auto()
    THERMOCOUPLE = auto()


REQUIRED_SENSOR_FLOATS = {
    SensorType.GPS: 3,
    SensorType.IMU: 4,
    SensorType.ACCELEROMETER: 3,
    SensorType.BAROMETER: 2,
    SensorType.TEMPERATURE: 1,
    SensorType.THERMOCOUPLE: 1
}


class IgnitorType(Enum):
    MAIN = auto()
コード例 #5
0
import collections
import struct
from enum import Enum
from .device_manager import DeviceType
from io import BytesIO
from typing import Any, Callable, Dict

from . import data_entry_id
from util.detail import LOGGER
from util.event_stats import Event
from main_window.data_entry_id import DataEntryIds

SINGLE_SENSOR_EVENT = Event('single_sensor')
CONFIG_EVENT = Event('config')

# Essentially a mini-class, to structure the header data. Doesn't merit its own class due to limited use,
# can be expanded if necessary elsewhere.
Header = collections.namedtuple('Header', ['subpacket_id', 'timestamp'])


# Parser's subpacket ids. Should not be used elsewhere, NOT DataIds
class SubpacketIds(Enum):
    MESSAGE = 0x01
    EVENT = 0x02
    CONFIG = 0x03
    # SINGLE_SENSOR's many values, added dynamically in constructor
    ACCELERATION_X = 0x10
    ACCELERATION_Y = 0x11
    ACCELERATION_Z = 0x12
    PRESSURE = 0x13
    BAROMETER_TEMPERATURE = 0x14
コード例 #6
0
import os
import threading
from enum import Enum
from typing import Dict, Union, Set, Callable, List, Optional
from collections import namedtuple
from sortedcontainers import SortedDict

import numpy as np

from util.detail import LOGS_DIR, SESSION_ID, LOGGER
from util.event_stats import Event
from .data_entry_id import DataEntryIds
from .device_manager import DeviceManager, DeviceType, FullAddress

BUNDLE_ADDED_EVENT = Event('bundle_added')

DataEntryKey = namedtuple('DataEntry', ['full_address', 'data_id'])
CallBackKey = namedtuple('DataEntry', ['device', 'data_id'])

AUTOSAVE_INTERVAL_S = 10

class RocketData:
    def __init__(self, device_manager: DeviceManager) -> None:
        """
        Timeset is dictionary of all of the time points mapped to a dictionary of DataEntryKey -> value.
        """
        self.device_manager = device_manager

        self.data_lock = threading.RLock()  # create lock ASAP since self.lock needs to be defined when autosave starts
        # Map: Time -> key-indexed list of data
        self.timeset: SortedDict[int, Dict[DataEntryKey, Union[int, float, str, Enum]]] = SortedDict()
コード例 #7
0
import queue
from enum import Enum
from threading import RLock
from typing import Dict

from digi.xbee.exception import TimeoutException
from PyQt5 import QtCore

from util.detail import LOGGER
from util.event_stats import Event
from main_window.device_manager import DeviceManager, DeviceType
from main_window.command_parser import CommandParser, CommandType, CommandParsingError
from connections.connection import Connection

COMMAND_SENT_EVENT = Event('command_sent')

class SendThread(QtCore.QThread):

    def __init__(self, connections: Dict[str, Connection], device_manager: DeviceManager, command_parser: CommandParser, parent=None) -> None:
        """Updates GUI, therefore needs to be a QThread and use signals/slots

        :param connections:
        :type connections:
        :param parent:
        :type parent:
        """
        QtCore.QThread.__init__(self, parent)
        self.connections = connections
        self.device_manager = device_manager
        self.command_parser = command_parser
コード例 #8
0
from util.event_stats import Event
from profiles.rocket_profile import RocketProfile

from .mapping import map_data, mapbox_utils
from .mapping.mapping_thread import MappingThread
from main_window.main_app import MainApp
from main_window.mplwidget import MplWidget

qtCreatorFile = os.path.join(BUNDLED_DATA, "qt_files", "comp_app.ui")

Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)

# The marker image, used to show where the rocket is on the map UI
MAP_MARKER = Image.open(mapbox_utils.MARKER_PATH).resize((12, 12), Image.LANCZOS)

LABLES_UPDATED_EVENT = Event('lables_updated')
MAP_UPDATED_EVENT = Event('map_updated')


class CompApp(MainApp, Ui_MainWindow):

    def __init__(self, connections: Dict[str, Connection], rocket_profile: RocketProfile) -> None:
        """

        :param connections:
        :param rocket_profile:
        """
        super().__init__(connections, rocket_profile)

        self.map_data = map_data.MapData()
        self.im = None  # Plot im
コード例 #9
0
from enum import Enum, auto
from threading import RLock
from typing import Iterable, List, Dict
from collections import namedtuple
from util.detail import LOGGER
from util.event_stats import Event

DEVICE_REGISTERED_EVENT = Event('device_registered')

FullAddress = namedtuple('FullAddress', ['connection_name', 'device_address'])
RegisteredDevice = namedtuple('RegisteredDevice',
                              ['device_type', 'full_address'])


class DeviceType(Enum):
    TANTALUS_STAGE_1_FLARE = auto()
    TANTALUS_STAGE_2_FLARE = auto()
    CO_PILOT_FLARE = auto()


_FLARE_DEVICE_TYPES = [
    DeviceType.TANTALUS_STAGE_1_FLARE,
    DeviceType.TANTALUS_STAGE_2_FLARE,
    DeviceType.CO_PILOT_FLARE,
]


def is_device_type_flare(device_type: DeviceType):
    return device_type in _FLARE_DEVICE_TYPES

コード例 #10
0
import random
import struct
import threading
import time

import connections.debug.radio_packets as radio_packets
from main_window.packet_parser import VERSION_ID_LEN
from ..connection import Connection, ConnectionMessage
from util.detail import LOGGER, REQUIRED_FLARE
from util.event_stats import Event

ARMED_EVENT = Event('armed')
DISARMED_EVENT = Event('disarmed')

PACKET_INTERVAL_S = 2


class DebugConnection(Connection):
    def __init__(self,
                 device_address: str,
                 device_id: int,
                 generate_radio_packets=True) -> None:
        """

        """
        self.device_address = device_address
        self.device_id = device_id
        self.start_time = time.time()
        self.lastSend = time.time()
        self.callback = None
        self.lock = threading.RLock(
コード例 #11
0
import collections
import struct
from enum import Enum
from .device_manager import DeviceType
from io import BytesIO
from typing import Any, Callable, Dict

from util.detail import LOGGER
from util.event_stats import Event
from main_window.data_entry_id import DataEntryIds, DataEntryValues


SINGLE_SENSOR_EVENT = Event('single_sensor')
CONFIG_EVENT = Event('config')
EVENT_EVENT = Event('event')
STATE_EVENT = Event('event')

# Essentially a mini-class, to structure the header data. Doesn't merit its own class due to limited use,
# can be expanded if necessary elsewhere.
Header = collections.namedtuple('Header', ['subpacket_id', 'timestamp'])

# Parser's subpacket ids. Should not be used elsewhere, NOT DataIds
class SubpacketIds(Enum):
    MESSAGE = 0x01
    EVENT = 0x02
    CONFIG = 0x03
    STATE = 0x05
    # SINGLE_SENSOR's many values, added dynamically in constructor
    ACCELERATION_X = 0x10
    ACCELERATION_Y = 0x11
    ACCELERATION_Z = 0x12
コード例 #12
0
from enum import IntEnum
from queue import SimpleQueue
from threading import Thread, RLock

from util.detail import LOGGER
from util.event_stats import Event

START_DELIMITER = 0x7E
ESCAPE_CHAR = 0x7D
ESCAPE_XOR = 0x20
XON = 0x11
XOFF = 0x13
NEEDS_ESCAPING = (START_DELIMITER, ESCAPE_CHAR, XON, XOFF)
XBEE_BROADCAST_ADDRESS = bytes.fromhex("000000000000FFFF")

FRAME_PARSED_EVENT = Event("frame_parsed")
SENT_TO_ROCKET_EVENT = Event("sent_to_rocket")


class FrameType(IntEnum):
    TX_REQUEST = 0x10
    TX_STATUS = 0x8B
    RX_INDICATOR = 0x90


class UnescapedDelimiterError(Exception):
    """
    Raises if there's an unescaped start delimiter.
    As per the XBee spec, this is eventually handled by discarding the packet so far and rebuilding.
    """
コード例 #13
0
from typing import Dict
from threading import RLock
from io import BytesIO, SEEK_END

from PyQt5 import QtCore
from PyQt5.QtCore import pyqtSignal

from main_window.data_entry_id import DataEntryIds
from util.detail import LOGGER
from util.event_stats import Event
from connections.connection import Connection, ConnectionMessage
from .rocket_data import RocketData
from .packet_parser import PacketParser
from .device_manager import DeviceManager, FullAddress

CONNECTION_MESSAGE_READ_EVENT = Event('connection_message_read')


class ReadThread(QtCore.QThread):
    sig_received = pyqtSignal()

    def __init__(self,
                 connections: Dict[str, Connection],
                 rocket_data: RocketData,
                 packet_parser: PacketParser,
                 device_manager: DeviceManager,
                 parent=None) -> None:
        """Updates GUI, therefore needs to be a QThread and use signals/slots

        :param connection:
        :type connection:
コード例 #14
0
from queue import SimpleQueue
from threading import Thread, RLock

from util.detail import LOGGER
from util.event_stats import Event

START_DELIMITER = 0x7E
ESCAPE_CHAR = 0x7D
ESCAPE_XOR = 0x20
XON = 0x11
XOFF = 0x13
NEEDS_ESCAPING = (START_DELIMITER, ESCAPE_CHAR, XON, XOFF)
SOURCE_ADDRESS = bytes.fromhex('0123456789ABCDEF')  # Dummy address
XBEE_BROADCAST_ADDRESS = bytes.fromhex('000000000000FFFF')

FRAME_PARSED_EVENT = Event('frame_parsed')
SENT_TO_ROCKET_EVENT = Event('sent_to_rocket')


class FrameType(IntEnum):
    TX_REQUEST = 0x10
    TX_STATUS = 0x8B
    RX_INDICATOR = 0x90


class UnescapedDelimiterError(Exception):
    """
    Raises if there's an unescaped start delimiter.
    As per the XBee spec, this is eventually handled by discarding the packet so far and rebuilding.
    """