Ejemplo n.º 1
0
class RTL433MsgGroup(ExportedState):
    def __init__(self, object_id):
        """Implements ITelemetryObject."""
        self.__cells = {}
        self.__last_heard_time = None

    def state_is_dynamic(self):
        """Overrides ExportedState."""
        return True

    def state_def(self):
        """Overrides ExportedState."""
        for d in super(RTL433MsgGroup, self).state_def():
            yield d
        for d in six.iteritems(self.__cells):
            yield d

    # not exported
    def receive(self, message_wrapper):
        """Implements ITelemetryObject."""
        self.__last_heard_time = message_wrapper.receive_time
        shape_changed = False
        for k, v in six.iteritems(message_wrapper.message):
            if k in _id_component_fields or k in _ignored_fields:
                continue
            if k not in self.__cells:
                shape_changed = True
                self.__cells[k] = LooseCell(value=None,
                                            type=object,
                                            writable=False,
                                            persists=False,
                                            label=k,
                                            sort_key='1' + k)
            self.__cells[k].set_internal(v)
        self.state_changed()
        if shape_changed:
            self.state_shape_changed()

    def is_interesting(self):
        """Implements ITelemetryObject."""
        return True

    def get_object_expiry(self):
        """implement ITelemetryObject"""
        return self.__last_heard_time + drop_unheard_timeout_seconds

    @exported_value(type=TimestampT(),
                    changes='explicit',
                    label='Last heard',
                    sort_key='9heard')
    def get_last_heard_time(self):
        return self.__last_heard_time
Ejemplo n.º 2
0
class Aircraft(ExportedState):
    def __init__(self, object_id):
        """Implements ITelemetryObject. object_id is the hex formatted address."""
        self.__last_heard_time = None
        self.__track = empty_track
        self.__call = None
        self.__ident = None
        self.__aircraft_type = None

    # not exported
    def receive(self, message_wrapper):
        message = message_wrapper.message
        cpr_decoder = message_wrapper.cpr_decoder
        receive_time = message_wrapper.receive_time
        self.__last_heard_time = receive_time
        # Unfortunately, gr-air-modes doesn't provide a function to implement this gunk -- imitating its output_flightgear code which
        data = message.data
        t = data.get_type()
        if t == 0:
            self.__track = self.__track._replace(altitude=TelemetryItem(
                air_modes.decode_alt(data['ac'], True) *
                _METERS_PER_FEET, receive_time))
            # TODO more info available here
        elif t == 4:
            self.__track = self.__track._replace(altitude=TelemetryItem(
                air_modes.decode_alt(data['ac'], True) *
                _METERS_PER_FEET, receive_time))
            # TODO more info available here
        elif t == 5:
            self.__ident = air_modes.decode_id(data['id'])
            # TODO more info available here
        elif t == 17:  # ADS-B
            bdsreg = data['me'].get_type()
            if bdsreg == 0x05:
                # TODO use unused info
                (altitude_feet, latitude, longitude, _range,
                 _bearing) = air_modes.parseBDS05(data, cpr_decoder)
                self.__track = self.__track._replace(
                    altitude=TelemetryItem(altitude_feet * _METERS_PER_FEET,
                                           receive_time),
                    latitude=TelemetryItem(latitude, receive_time),
                    longitude=TelemetryItem(longitude, receive_time),
                )
            elif bdsreg == 0x06:
                # TODO use unused info
                (_ground_track, latitude, longitude, _range,
                 _bearing) = air_modes.parseBDS06(data, cpr_decoder)
                self.__track = self.__track._replace(
                    latitude=TelemetryItem(latitude, receive_time),
                    longitude=TelemetryItem(longitude, receive_time),
                )
            elif bdsreg == 0x08:
                (self.__call,
                 self.__aircraft_type) = air_modes.parseBDS08(data)
            elif bdsreg == 0x09:
                subtype = data['bds09'].get_type()
                if subtype == 0:
                    (velocity, heading, vertical_speed,
                     _turn_rate) = air_modes.parseBDS09_0(data)
                    # TODO: note we're stuffing the heading in as track angle. Is there something better to do?
                    self.__track = self.__track._replace(
                        h_speed=TelemetryItem(
                            velocity * _KNOTS_TO_METERS_PER_SECOND,
                            receive_time),
                        heading=TelemetryItem(heading, receive_time),
                        track_angle=TelemetryItem(heading, receive_time),
                        v_speed=TelemetryItem(vertical_speed, receive_time),
                        # TODO add turn rate
                    )
                elif subtype == 1:
                    (velocity, heading,
                     vertical_speed) = air_modes.parseBDS09_1(data)
                    self.__track = self.__track._replace(
                        h_speed=TelemetryItem(
                            velocity * _KNOTS_TO_METERS_PER_SECOND,
                            receive_time),
                        heading=TelemetryItem(heading, receive_time),
                        track_angle=TelemetryItem(heading, receive_time),
                        v_speed=TelemetryItem(vertical_speed, receive_time),
                        # TODO reset turn rate?
                    )
                else:
                    # TODO report
                    pass
            else:
                # TODO report
                pass
        else:
            # TODO report
            pass
        self.state_changed()

    def is_interesting(self):
        """
        Implements ITelemetryObject. Does this aircraft have enough information to be worth mentioning?
        """
        # TODO: Loosen this rule once we have more efficient state transfer (no polling) and better UI for viewing them on the client.
        return \
            self.__track.latitude.value is not None or \
            self.__track.longitude.value is not None or \
            self.__call is not None or \
            self.__aircraft_type is not None

    def get_object_expiry(self):
        """implement ITelemetryObject"""
        return self.__last_heard_time + drop_unheard_timeout_seconds

    @exported_value(type=TimestampT(),
                    changes='explicit',
                    sort_key='100',
                    label='Last heard')
    def get_last_heard_time(self):
        return self.__last_heard_time

    @exported_value(type=six.text_type,
                    changes='explicit',
                    sort_key='020',
                    label='Call')  # TODO naming may be wrong
    def get_call(self):
        return self.__call

    @exported_value(type=int,
                    changes='explicit',
                    sort_key='050',
                    label='Ident')  # TODO naming may be wrong
    def get_ident(self):
        return self.__ident

    @exported_value(type=six.text_type,
                    changes='explicit',
                    sort_key='020',
                    label='Aircraft type')
    def get_aircraft_type(self):
        return self.__aircraft_type

    @exported_value(type=Track, changes='explicit', sort_key='010', label='')
    def get_track(self):
        return self.__track
Ejemplo n.º 3
0
class APRSStation(ExportedState):
    def __init__(self, object_id):
        self.__last_heard_time = None
        self.__address = object_id
        self.__track = empty_track
        self.__status = u''
        self.__symbol = u''
        self.__last_comment = u''
        self.__last_parse_error = u''

    def receive(self, message):
        """implement ITelemetryObject"""
        self.__last_heard_time = message.receive_time
        for fact in message.facts:
            if isinstance(fact, KillObject):
                # Kill by pretending the object is ancient.
                self.__last_heard_time = 0
            if isinstance(fact, Position):
                self.__track = self.__track._replace(
                    latitude=TelemetryItem(fact.latitude,
                                           message.receive_time),
                    longitude=TelemetryItem(fact.longitude,
                                            message.receive_time),
                )
            if isinstance(fact, Altitude):
                conversion = _FEET_TO_METERS if fact.feet_not_meters else 1
                self.__track = self.__track._replace(altitude=TelemetryItem(
                    fact.value * conversion, message.receive_time), )
            if isinstance(fact, Velocity):
                self.__track = self.__track._replace(
                    h_speed=TelemetryItem(
                        fact.speed_knots * _KNOTS_TO_METERS_PER_SECOND,
                        message.receive_time),
                    track_angle=TelemetryItem(fact.course_degrees,
                                              message.receive_time),
                )
            elif isinstance(fact, Status):
                # TODO: Empirically, not always ASCII. Move this implicit decoding off into parse stages.
                self.__status = unicode(fact.text)
            elif isinstance(fact, Symbol):
                self.__symbol = unicode(fact.id)
            else:
                # TODO: Warn somewhere in this case (recognized by parser but not here)
                pass
        self.__last_comment = unicode(message.comment)
        if len(message.errors) > 0:
            self.__last_parse_error = '; '.join(message.errors)
        self.state_changed()

    def is_interesting(self):
        """implement ITelemetryObject"""
        return True

    def get_object_expiry(self):
        """implement ITelemetryObject"""
        return self.__last_heard_time + drop_unheard_timeout_seconds

    @exported_value(type=TimestampT(),
                    changes='explicit',
                    sort_key='100',
                    label='Last heard')
    def get_last_heard_time(self):
        return self.__last_heard_time

    @exported_value(type=unicode,
                    changes='explicit',
                    label='Address/object ID')
    def get_address(self):
        return self.__address

    @exported_value(type=Track, changes='explicit', sort_key='010', label='')
    def get_track(self):
        return self.__track

    @exported_value(type=unicode,
                    changes='explicit',
                    sort_key='020',
                    label='Symbol')
    def get_symbol(self):
        """APRS symbol table identifier and symbol."""
        return self.__symbol

    @exported_value(type=unicode,
                    changes='explicit',
                    sort_key='080',
                    label='Status')
    def get_status(self):
        """String status text."""
        return self.__status

    @exported_value(type=unicode,
                    changes='explicit',
                    sort_key='090',
                    label='Last message comment')
    def get_last_comment(self):
        return self.__last_comment

    @exported_value(type=NoticeT(always_visible=False),
                    sort_key='000',
                    changes='explicit')
    def get_last_parse_error(self):
        return self.__last_parse_error
Ejemplo n.º 4
0
class WSPRStation(ExportedState):
    __last_heard = 0
    __snr = None
    __frequency = None
    __call = None
    __grid = None
    __txpower = None

    def __init__(self, object_id):
        pass

    def receive(self, message):
        self.__last_heard = message.time
        self.__snr = message.snr
        self.__frequency = message.frequency
        self.__call = message.call
        self.__grid = message.grid
        self.__txpower = message.txpower
        self.state_changed()

    def is_interesting(self):
        """Every WSPR message is about as interesting as another, I suppose."""
        return True

    def get_object_expiry(self):
        return self.__last_heard + 30 * MINUTES

    @exported_value(type=TimestampT(), changes='explicit', label='Last heard')
    def get_last_heard(self):
        return self.__last_heard

    @exported_value(type=QuantityT(units.dB), changes='explicit', label='SNR')
    def get_snr(self):
        return self.__snr or -999

    @exported_value(type=QuantityT(units.MHz),
                    changes='explicit',
                    label='Frequency')
    def get_frequency(self):
        return self.__frequency or 0

    @exported_value(type=unicode, changes='explicit', label='Call')
    def get_call(self):
        return self.__call or ''

    @exported_value(type=unicode, changes='explicit', label='Grid')
    def get_grid(self):
        return self.__grid or ''

    @exported_value(type=QuantityT(units.dBm),
                    changes='explicit',
                    label='Tx Power')
    def get_txpower(self):
        return self.__txpower or 0

    @exported_value(type=Track, changes='explicit', label='Track')
    def get_track(self):
        if self.__grid:
            latitude, longitude = grid_to_lat_long(self.__grid)
            track = Track(latitude=TelemetryItem(latitude, self.__last_heard),
                          longitude=TelemetryItem(longitude,
                                                  self.__last_heard))
            return track
        else:
            return empty_track