Verizon FiOS Quantum Gateway device_tracker Platform

Hey everyone,

I recently moved to a new place with FiOS and have the standard Quantum Gateway 1100. I wanted to be able to use the gateway for device tracking because I have several other routers connected to it via MoCA.

I started by SSHing into the router, but besides viewing a few logs there is basically no other information available through that interface. So I observed that the frontend has a list of connected devices, and by querying http://myfiosgateway.com/api/devices, a JSON list of devices is returned.

The only tricky part was the login/authentication. After looking through the minified JS, I figured out how the password combined with the password salt and how to log in.

I explicitly log out on every update because there is a maximum number of concurrent users enforced. I ran in to problems without this.

Anyway, please take a look at https://github.com/cisasteelersfan/quantum_gateway. I’d like to eventually add this into home assistant via creating a PyPI package, but wanted others to test on their routers first. Simply add the device_tracker folder from the repo inside of the custom_components folder.

Thanks, and I welcome any and all feedback!

1 Like

So far so good! Will update if any problems. I appreciate you adding the platform.

Update: working great! I’m using along with nmap and it is working much better than nmap alone,

Hello, this is great. Thank you for making and sharing it!

I am having trouble getting it to work with Hass.io – I tried copying the text of the .py files into a newly created custom_components/device_tracker directory, but it still tells me “Platform not found: device_tracker.quantum_gateway” when I validate the configuration.

Any idea what I might be doing wrong? I am very new to this, so please forgive me if this is a dumb question.

Hey there, no problem, I’m glad people are using it! I hope I can help you get it working for you.

Your folder structure needs to look like this:

.homeassistant/ <- or whatever folder contains your home assistant configuration
    custom_components/
        device_tracker/
            quantum_gateway.py <- this name must match what you have in your configuration. Stick with quantum_gateway

I’m actually currently in the process of refactoring the code so that I can upload to Pypi and get it merged into Home Assistant so you don’t have to deal with all of this! I would recommend you copy quantum_gateway.py from here at this point https://github.com/cisasteelersfan/quantum_gateway/blob/4d10bdce79d199e43f5f0aa0a1fb570a9c13a758/device_tracker/quantum_gateway.py

Let me know if it works out for you and if you have any other questions

1 Like

This is now included in HomeAssistant: https://www.home-assistant.io/components/device_tracker.quantum_gateway/

1 Like

This is great, thank you!

Does anyone know if this API allows for querying the public IP address and/or wan side default gateway? …if the wan side gateway is available, a device tracker for “internet” could be added, and possibly target a ping tracker to monitor the first hop latency to the internet.

Yes, in the management of my router I can see the public IP and wan side default gateway. Someone could take a look at my github repo to see how to log in to the router, and then grab the IP info.

(first post so if this is old news or not applicable…sorry)

Anyways, I’ve been playing around with this component for the past week, and in addition to the API methods, there also appears to be log files that can be scraped for component info like RSSI and the Public IP as tsimons78 requested.

Looking into the API a bit more, I found this link (google cache as the site went down in the last 10 minutes after I found it):
Quantum Gateway Vulnerability Disclosure

The log files listed in the link are available to ANY connected device on the LAN/WLAN interface, without authentication.

Specifically, the log:
http://192.168.1.1:1901/logs/sdhl_operation - contains WWAN connected devices and their stats,external IP, and other info.

Device Info from log file:

{ x_d4a928_cur-snr=30,
associateddevicemacaddress=5c:cf:7f:7d:d4:2b,
x_d4a928_packetstransmitted=3774087,
x_d4a928_packetsreceived=92591,
x_d4a928_standard=N,
sample={x_d4a928_airtime_allocation=0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
x_d4a928_curtxmodulationrate=58.5,58.5,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,72.2,72.2,72.2,
currssi=-42,-42,-42,-42,-42,-42,-42,-42,-41,-41,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,
x_d4a928_currxmodulationrate=54,54,54,54,54,54,54,54,48,48,54,54,54,54,54,54,54,54,54,54},
x_d4a928_airtime_allocation=0.0%,
x_d4a928_transceiversetting=NA x 3 : 1,
x_d4a928_curtxmodulationrate=72.2 Mbps,
currssi=-42,
x_d4a928_currxmodulationrate=54 Mbps,
x_d4a928_channel=1,
x_d4a928_maxtxmodulationrate=72.2 Mbps,
x_d4a928_curbandwidth=20Mhz,
x_d4a928_maxrxmodulationrate=72.2 Mbps,
associateddeviceauthenticationstate=true}

The only ‘problem’ I can see with this being used for real-time tracking is that it is only logged/sent once an hour. So while it should be good to keep track of your external IP - it prob wont for RSSI tracking unless we can trigger the log to update on demand. (this might be possible but I have not looked into it this far yet)

in case anyone wants to try, here is a quick script I created to scrap that log for the MAC, RSSI, and External IP, and get the names from the mac address: (This is also my first Python script, and is just a “proof of concept” that data can be extracted and used from those files)

import urllib3

#Connect with quantum_gateway to find the names of the devices
from quantum_gateway import QuantumGatewayScanner
gateway = QuantumGatewayScanner('192.168.1.1', 'password')
gateway.success_init
gateway.scan_devices()

#Read log from router
url = 'http://192.168.1.1:1901/logs/sdhl_operation'
http = urllib3.PoolManager()
logData = http.request('GET', url)
'
#Split log into readable lines
array = logData.data.decode().split('\n')

#Create Variables to store found Device Info and External IP
externalip = ""
deviceInfo = []

#Read each Line of the log to find lines with Device Data and External IP
for line in array:

    if line.find('justlog.tr98.wificlients,wlanconfiguration/1/associateddevice,[{') > 0:
        deviceInfo.append(line)

    elif line.find(',justlog.tr98.networkresource,externalipaddress,') > 0 and externalip == "":
        exip = line.split(',')
        externalip = exip[(len(exip) -1)]
        print("External IP: " + externalip)

#Select and split the last object in the deviceInfo array as it (should) be the latest
deviceData = deviceInfo[(len(deviceInfo) - 1)].split(';')

#Go through each device
for device in deviceData:

    #Create Variables to store found info before we go to a new device
    foundrssi = 0
    foundname = ""
    runonce = 0
    data = device.split(',')

    #Look through the date each device provides to find RSSI, MAC, and name.
    for item in data:

        #RSSI
        if item.find('currssi=') > 0 and foundrssi == 0:
            rssi = item.split('=')
            foundrssi = rssi[1]

        #MAC Address and Name
        elif item.find('associateddevicemacaddress=') > 0 and foundname == "":
            mac = item.split("=")

            foundname = gateway.get_device_name(mac[1])
        #Print to screen(for now) 
        elif foundrssi != 0 and foundname != "" and runonce == 0:
            printstring = "Device Name: " + foundname
            rssistring = "Device RSSI: " + foundrssi
            print(printstring)
            print(rssistring)
            runonce = 1

gateway._log_out()

Here is the output I get:

External IP: ...
Device Name: Onkyo
Device RSSI: -39
Device Name: PowerMeter
Device RSSI: -42
Device Name: ESPSensor02
Device RSSI: -40
Device Name: DeskLamp
Device RSSI: -40
Device Name: GH_Heater
Device RSSI: -55
Device Name: amazon-6d6ffd85f
Device RSSI: -47
Device Name: Google-Home-Mini-LR
Device RSSI: -43
Device Name: Google-Home-Mini-KT
Device RSSI: -47
Device Name: new-host-1
Device RSSI: -54
Device Name: ESPSensor03
Device RSSI: -54

This stopped working a little a week ago for me with the following
Firmware Version: 02.02.00.13

Hardware Version: 1.03

UI Version: v1.0.388

A recent update to the firmware is forcing an unsigned cert to be used now. Documented here : https://github.com/cisasteelersfan/quantum_gateway/issues/7 .

Hey @cisasteelersfan, is it possible to get the device IP as well?

I think that would be possible, but unfortunately I no longer have Fios service. If you or anyone else is interested in taking over this project, let me know and we can transfer ownership of the Pypi repository.

I tried using this integration, but get the following error:

Logger: homeassistant
Source: components/quantum_gateway/device_tracker.py:63
First occurred: 7:57:01 AM (494 occurrences)
Last logged: 9:35:27 AM

Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/device_tracker/legacy.py", line 352, in async_device_tracker_scan
    found_devices = await scanner.async_scan_devices()
  File "/usr/src/homeassistant/homeassistant/components/device_tracker/legacy.py", line 829, in async_scan_devices
    return await self.hass.async_add_executor_job(self.scan_devices)
  File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/homeassistant/homeassistant/components/quantum_gateway/device_tracker.py", line 63, in scan_devices
    connected_devices = self.quantum.scan_devices()
  File "/usr/local/lib/python3.8/site-packages/quantum_gateway.py", line 33, in scan_devices
    self._get_connected_devices()
  File "/usr/local/lib/python3.8/site-packages/quantum_gateway.py", line 41, in _get_connected_devices
    devices = json.loads(devices_raw.text)
  File "/usr/local/lib/python3.8/json/__init__.py", line 357, in loads
    return _default_decoder.decode(s)
  File "/usr/local/lib/python3.8/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/local/lib/python3.8/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

My config:

- platform: quantum_gateway
  host: 192.168.1.1
  ssl: true
  password: **************
  new_device_defaults:
    track_new_devices: true