Exemple #1
0
    def connect_signalk(self):
        print 'connect...'
        connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        socketio.emit(
            'flush'
        )  # unfortunately needed to awaken socket for client messages
        try:
            connection.connect(('localhost', DEFAULT_PORT))
        except:
            socketio.sleep(2)
            return
        print 'connected'

        self.client = LineBufferedNonBlockingSocket(connection)
        self.client.send('{"method": "list"}\n')
        self.client.flush()

        self.poller = select.poll()
        self.poller.register(connection, select.POLLIN)
        t0 = time.time()
        self.list_values = {}
        while time.time() - t0 < 3:
            self.client.recv()
            line = self.client.readline()
            if line:
                self.list_values = line
                return

        self.client.socket.close()
        self.client = False
Exemple #2
0
class MyNamespace(Namespace):
    def __init__(self, name):
        super(Namespace, self).__init__(name)
        socketio.start_background_task(target=self.background_thread)
        self.client = False
        self.polls = {}

    def connect_signalk(self):
        print 'connect...'
        connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        socketio.emit(
            'flush'
        )  # unfortunately needed to awaken socket for client messages
        try:
            connection.connect(('localhost', DEFAULT_PORT))
        except:
            socketio.sleep(2)
            return
        print 'connected'

        self.client = LineBufferedNonBlockingSocket(connection)
        self.client.send('{"method": "list"}\n')
        self.client.flush()

        self.poller = select.poll()
        self.poller.register(connection, select.POLLIN)
        t0 = time.time()
        self.list_values = {}
        while time.time() - t0 < 3:
            self.client.recv()
            line = self.client.readline()
            if line:
                self.list_values = line
                return

        self.client.socket.close()
        self.client = False

    def background_thread(self):
        print 'processing clients'
        x = 0
        polls_sent = {}
        while True:
            socketio.sleep(.25)
            if self.client:
                polls = {}
                for sid in self.polls:
                    for poll in self.polls[sid]:
                        polls[poll] = True
                t = time.time()
                for message in polls:
                    if not message in polls_sent or \
                       t - polls_sent[message] > 1:
                        #print 'msg', message
                        self.client.send(message + '\n')
                        polls_sent[message] = t

                self.client.flush()

                events = self.poller.poll(0)
                if not events:
                    continue

                event = events.pop()
                fd, flag = event
                if flag & (select.POLLHUP | select.POLLERR | select.POLLNVAL) \
                   or not self.client.recv():
                    print 'disconnected'
                    self.client.socket.close()
                    socketio.emit('signalk_disconnect', self.list_values)
                    self.client = False
                    continue

                while True:
                    line = self.client.readline()
                    if not line:
                        break
                    #print 'line', line
                    try:
                        #data = {'data': json.loads(line.rstrip())}
                        #print 'data', data
                        socketio.emit('signalk', line.rstrip())
                    except:
                        socketio.emit('log', line)
                        print 'error: ', line.rstrip()
                        break
            else:
                if self.polls:
                    self.connect_signalk()
                if self.client:
                    socketio.emit('signalk_connect', self.list_values)

    def on_signalk(self, message):
        #print 'msg',  message
        self.client.send(message + '\n')

    def on_signalk_poll(self, message):
        #print 'message', message
        if message == 'clear':
            self.polls[request.sid] = {}
            return
        self.polls[request.sid][message] = True

    #def on_disconnect_request(self):
    #    disconnect()

    def on_ping(self):
        emit('pong')

    def on_connect(self):
        #self.clients[request.sid] = Connection()
        #print('Client connected', request.sid, len(self.clients))
        print('Client connected', request.sid)
        self.polls[request.sid] = {}
        if self.client:
            socketio.emit('signalk_connect', self.list_values)

    def on_disconnect(self):
        #client = self.clients[request.sid].client
        #if client:
        #    client.socket.close()
        del self.polls[request.sid]
        if not self.polls:
            self.client.socket.close()
            self.client = False
            print 'closed signalk client'
        print('Client disconnected', request.sid, len(self.polls))
Exemple #3
0
def nmea_bridge_process(pipe=False):
    import os
    sockets = []
    watchlist = [
        'ap.enabled', 'ap.mode', 'ap.heading_command', 'imu/pitch', 'imu/roll',
        'imu/heading_lowpass', 'gps.source', 'wind.speed', 'wind.direction',
        'wind.source'
    ]

    def setup_watches(client, watch=True):
        for name in watchlist:
            client.watch(name, watch)

    def on_con(client):
        print 'nmea client connected'
        if sockets:
            setup_watches(client)

    # we actually use a local connection to the server to simplify logic
    print 'nmea try connections'
    while True:
        try:
            client = SignalKClient(on_con, 'localhost', autoreconnect=True)
            break
        except:
            time.sleep(2)
    print 'nmea connected'

    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setblocking(0)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    port = 10110
    try:
        server.bind(('0.0.0.0', port))
    except:
        print 'nmea_bridge: bind failed.'
        exit(1)
    print 'listening on port', port, 'for nmea connections'

    server.listen(5)
    max_connections = 10
    READ_ONLY = select.POLLIN | select.POLLHUP | select.POLLERR

    ap_enabled = 'N/A'
    ap_mode = 'N/A'
    ap_heading_command = 180
    addresses = {}
    cnt = 0

    poller = select.poll()
    poller.register(server, READ_ONLY)
    fd_to_socket = {server.fileno(): server}
    windspeed = 0

    gps_source = wind_source = False
    while True:
        if sockets:
            timeout = 100
        else:
            timeout = 10000
        events = poller.poll(timeout)
        while events:
            event = events.pop()
            fd, flag = event
            sock = fd_to_socket[fd]
            if sock == server:
                connection, address = sock.accept()
                if len(sockets) == max_connections:
                    connection.close()
                else:
                    if not sockets:
                        setup_watches(client)
                    sock = LineBufferedNonBlockingSocket(connection)
                    sockets.append(sock)
                    print 'new connection: ', address
                    addresses[sock] = address
                    fd = sock.socket.fileno()
                    fd_to_socket[fd] = sock

                    poller.register(sock.socket, READ_ONLY)

            elif (flag & (select.POLLHUP | select.POLLERR)) or \
                 (flag & select.POLLIN and not sock.recv()):
                print 'lost connection: ', addresses[sock]
                sockets.remove(sock)
                #                addresses.remove(sock)
                if not sockets:
                    setup_watches(client, False)
                poller.unregister(sock.socket)
                fd = sock.socket.fileno()
                del fd_to_socket[fd]
                sock.socket.close()


#            elif flag & select.POLLOUT:
#                sock.flush()
#                if not sock.out_buffer:
#                    poller.register(sock.socket, READ_ONLY)

        for sock in sockets:
            line = sock.readline()
            if not line:
                continue

            if line[:6] == '$GPRMC':
                if pipe and gps_source != 'internal':
                    data = line[7:len(line) - 3].split(',')
                    timestamp = float(data[0])
                    speed = float(data[6])
                    heading = float(data[7])

                    pipe.send(
                        {
                            'gps': {
                                'timestamp': timestamp,
                                'track': heading,
                                'speed': speed
                            }
                        }, False)

            elif line[0] == '$' and line[3:6] == 'MVW':
                if pipe and wind_source != 'internal':
                    winddata = wind.parse_nmea(line)
                    if winddata:
                        pipe.send({'wind': winddata}, False)

            elif line[0] == '$' and line[3:6] == 'APB':
                data = line[7:len(line) - 3].split(',')
                if not ap_enabled:
                    client.set('ap.enabled', True)

                if ap_mode != 'gps':
                    client.set('ap.mode', 'gps')

                if abs(ap_heading_command - float(data[7])) > .1:
                    client.set('ap.heading_command', float(data[7]))

        msgs = client.receive()
        for name in msgs:
            data = msgs[name]
            value = data['value']

            msg = False
            if name == 'ap.enabled':
                ap_enabled = value
            elif name == 'ap.mode':
                ap_mode = value
            elif name == 'ap.heading_command':
                ap_heading_command = value
            elif name == 'imu/pitch':
                msg = 'APXDR,A,%.3f,D,PTCH' % value
            elif name == 'imu/roll':
                msg = 'APXDR,A,%.3f,D,ROLL' % value
            elif name == 'imu/heading_lowpass':
                msg = 'APHDM,%.3f,M' % value
            elif name == 'gps.source':
                gps_source = value
            elif name == 'wind.speed':
                windspeed = value
            elif name == 'wind.direction':
                msg = 'APMWV,%.1f,R,%.1f,K,A' % (value, windspeed)
            elif name == 'wind.source':
                wind_source = value

            if msg:
                msg = '$' + msg + '*' + cksum(msg) + '\r\n'
                for sock in sockets:
                    sock.send(msg)
                    sock.flush()