https://github.com/yubars/mbb
Raw File
Tip revision: cd5de904332d33adabbc4793a87af7406ff26250 authored by yubars on 27 May 2014, 20:18:40 UTC
Create speed.py
Tip revision: cd5de90
pathinfo.py
#!/usr/bin/python

import copy
import threading
import time
import zmq
import sys

from usbmodem_msg_pb2 import *

import interfaceinfo


MESSAGES = {
  'event.radio.access.NetworkModeChangeEvent': {
    'class': NetworkModeChangeEvent,
  },
  'event.radio.access.NetworkSubmodeChangeEvent': {
    'class': NetworkSubmodeChangeEvent,
  },
  'event.radio.access.SignalStrengthChangeEvent': {
    'class': SignalStrengthChangeEvent,
  },
  'event.radio.access.LocationChangeEvent': {
    'class': LocationChangeEvent,
  },
  'event.radio.access.SNRChangeEvent': {
    'class': SNRChangeEvent,
  },
  'event.radio.wcdma.RRCStateChangeEvent': {
    'class': RRCStateChangeEvent,
  },
  'state.generic.CurrentNetworkState': {
    'class': CurrentNetworkState,
  },
}

# RRC and network
MODE = { 
 '0': 'No service', '3': 'GSM', '5': 'WCDMA'
}
SUBMODE = { 
 '0': 'No service', '1': 'GSM', '2': 'GPRS',
 '3': 'EDGE', '4': 'WCDMA', '5': 'HSDPA', '6': 'HSUPA',
 '7': 'HSDPA+HSUPA', '9': 'HSPA+'
}
RRC = { 
 '0': 'Disconnected', '1': 'Connecting', '2': 'FACH',
 '3': 'DCH', '4': 'PCH', '5': 'URA-PCH'
}


INTF_TO_MCC_MNC = { 'ppp0': '24201', 'ppp1': '24202', 'ppp2': '24007', 'ppp3': '24205' }
SUB_ADDR        = "tcp://*:5550" # public address and port (for subscribers)

MCC_MNC_TO_INTF = { v:k for k, v in INTF_TO_MCC_MNC.items() } # reverse

_thread       = None
_stop         = True
_mbbn_dict    = {}


def _process_message(intf, event, msg):
    global _mbbn_dict
    if not intf in _mbbn_dict:
        return # not monitoring this one
    
    if event == 'event.radio.access.NetworkModeChangeEvent':
        _mbbn_dict[intf]['mode'] = MODE[str(msg.currentNetworkMode)]
    
    elif event == 'event.radio.access.NetworkSubmodeChangeEvent':
        _mbbn_dict[intf]['submode'] = SUBMODE[str(msg.currentNetworkSubmode)]
    
    elif event == 'event.radio.access.SignalStrengthChangeEvent':
        _mbbn_dict[intf]['rssi'] = msg.currentRssi
    
    elif event == 'event.radio.access.LocationChangeEvent':
        _mbbn_dict[intf]['lac'] = msg.currentLac
        _mbbn_dict[intf]['cellid'] = msg.currentCellId
    
    elif event == 'event.radio.access.SNRChangeEvent':
        _mbbn_dict[intf]['rscp'] = msg.currentRscp
        _mbbn_dict[intf]['ecio'] = msg.currentEcio
    
    elif event == 'event.radio.wcdma.RRCStateChangeEvent':
        _mbbn_dict[intf]['rrc'] = RRC[str(msg.currentRRCState)]
    
    elif event == 'state.generic.CurrentNetworkState':
        # this one comes periodically, every 5 seconds
        _mbbn_dict[intf]['uptime'] = msg.uptime
        #pppiface = msg.iface
        #ipAddr = msg.ipAddress
        _mbbn_dict[intf]['ipAddr']    = str(msg.ipAddress)
        _mbbn_dict[intf]['mode']    = MODE[str(msg.networkMode)]
        _mbbn_dict[intf]['submode'] = SUBMODE[str(msg.networkSubmode)]
        _mbbn_dict[intf]['rssi']    = msg.rssi
        _mbbn_dict[intf]['lac']     = msg.lac
        _mbbn_dict[intf]['cellid']  = msg.cellId
        _mbbn_dict[intf]['rrc']     = RRC[str(msg.RRCState)]
        _mbbn_dict[intf]['rscp']     = msg.rscp
        _mbbn_dict[intf]['ecio']     = msg.ecio


def _read_from_zmq(s_zmq, poller):
    # wait up to 100 msecs for new messages
    timeout = dict(poller.poll(100))
    if timeout.get(s_zmq) != zmq.POLLIN:
        return
    
    msg_parts = s_zmq.recv_multipart(flags=zmq.NOBLOCK)
    try:
        [topic, node, data] = msg_parts
    except:
        [topic, data] = msg_parts

    (mcc_mnc, event) = topic.split(".", 1)
    if not event in MESSAGES:
        print >> sys.stderr, "Unknown message from ZMQ %s!" % event
        return

    msg = MESSAGES[event]["class"]()
    msg.ParseFromString(data)
    _process_message(MCC_MNC_TO_INTF[mcc_mnc], event, msg)


def _update_subscriptions(s_zmq, intf_to_topic):
    global _mbbn_dict
    # query current state of interfaces
    intfs = interfaceinfo.getinfo()
    for intf, state in intfs.items():
        if state == 'UP':
            if not intf in intf_to_topic:
                # interface is up, we are not subscribed
                mcc_mnc = INTF_TO_MCC_MNC[intf]
                intf_to_topic[intf] = mcc_mnc
                _mbbn_dict[intf] = {} # allocate empty dict for interface
                s_zmq.setsockopt(zmq.SUBSCRIBE, mcc_mnc)
        else:
            if intf in intf_to_topic:
                # interface is down, we are subscribed
                s_zmq.setsockopt(zmq.UNSUBSCRIBE, intf_to_topic[intf])
                del _mbbn_dict[intf] # clean up
                del intf_to_topic[intf]
    return intf_to_topic
 

def _listen():
    global _stop
    try:
        context = zmq.Context()
        s_zmq = context.socket(zmq.SUB)
        s_zmq.connect(SUB_ADDR)
        s_zmq.setsockopt(zmq.LINGER, 0)

        time.sleep(0.1) # wait to avoid exception about poller
        poller = zmq.Poller()
        poller.register(s_zmq, zmq.POLLIN)
        try:
            intf_to_topic = {}
            while not _stop:
                intf_to_topic = _update_subscriptions(s_zmq, intf_to_topic)
                _read_from_zmq(s_zmq, poller)
        
        finally:
            poller.unregister(s_zmq)
            s_zmq.close()
            context.term()

    finally:
        global _thread
        _thread = None # signals that this thread has ended


def getinfo():
    # return a copy of the current state
    global _mbbn_dict
    return copy.deepcopy(_mbbn_dict)


def start():
    global _thread
    if not _thread is None:
        raise RuntimeError("interfaceinfo has been started already!")
    
    global _stop
    _stop = False
    _thread = threading.Thread(target = _listen)
    _thread.daemon = True
    _thread.start()


def stop():
    global _stop
    _stop = True
    global _thread
    while not _thread is None:
        time.sleep(0.01) # wait for thread to end
back to top