Writing a KDE Plasmoid to display JioFi Stats
Tags: kde, widget, javascript, linux
Published: 2020-07-24 19:00:55


I've been using Manjaro KDE for a while now, and thought I'd make a KDE Widget to display the information from connected JioFi M2S Router.


### Reversing the protocol?
Since we are able to view the details of the router if we visit `jiofi.local.html`, I visited the site, and checked for networks tab for an API, I was under the assumption that the source code would be obfuscated , and looking at the JavaScript would be tedious. Not being able to gain anything from the Networks tab, I tried viewing the source, and the following snippet caught my eye.

```html
	</head>
	<body>
		<input type="hidden" id="connectedStatus" value="Attached" />
		<input type="hidden" id="imsi" value="XXXX" />
		<input type="hidden" id="batterystatus" value="Discharging" />
		<input type="hidden" id="batterylevel" value="41%" />
		<input type="hidden" id="signalstrength" value="Normal" />
		<input type="hidden" id="noOfClient" value="3" />
		<input type="hidden" id="devicemodel" value="M2S" />
    .
    .
    .
```

Not much reversing needed anymore, I could just parse the DOM ( As I'd realize later it's hard to do HTML parsing ) or write a regex to extract these values to display in the widget

### Writing the widget
I found this [tutorial](http://juanmanueldehoyos.com/how-to-write-a-small-plasmoid-fo/) which saved me a lot of time.
A Qt plasmoid is made up of two files the `metadata.desktop` file which contains the widget metadata, and the main `.qml` file which renders the widget.

So I can write a widget with two columns of text, to display the details I want, I ended up adding some emoji's to make it prettier
```qml
  Column {
    Text {
      text:"🔋"+ root.chargeIcon+ " : "+ root.batteryPercentage
      font.pointSize: 24
    }
    Text {
      text:"📱 : "+ root.noOfClients
      font.pointSize: 24
    }
    Text {
      text: "📶 : "+root.signalStrength
      font.pointSize: 24
    }
  }
```

Then following along the tutorial, I proceeded to add a timer , which will perform an XMLHttpRequest, parse the response body using regex, and update the global variables.
I'm trying to match type text between the fixed input tags by using regular expressions
`htmlBody.match(/<input type="hidden" id="batterystatus" value="(.*)" \/>/)[1]`

```qml
function parseBody(x){
    if (x.responseText) {
      // Couldn't parse the HTML , so using regex to extract the values
      var htmlBody = x.responseText;
      root.batteryPercentage = htmlBody.match(/<input type="hidden" id="batterystatus" value="(.*)" \/>/)[1]
      root.noOfClients = htmlBody.match(/<input type="hidden" id="noOfClient" value="(.*)" \/>/)[1]
      root.signalStrength = htmlBody.match(/<input type="hidden" id="signalstrength" value="(.*)" \/>/)[1]
      var batteryStatus = htmlBody.match(/<input type="hidden" id="batterystatus" value="(.*)" \/>/)[1]
      if ( batteryStatus == "Charging" ) {
        root.chargeIcon = " ⚡";
      }
    }
  }

  function request(url, parseBody) {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = (function f() {parseBody(xhr)});
    xhr.open('GET', url, true);
    xhr.send();
  }

  Timer {
    running: true
    triggeredOnStart: true
    interval: 60000
    onTriggered: request("http://jiofi.local.html", parseBody)
  }
```

And we're done, It finally looks something like this

![JioFi Plasmoid](https://github.com/anandubajith/jiofi-plasmoid/raw/master/screenshot.png)

Originally written on my blog here: https://anandu.net/blog/making-a-kde-plasmoid/
Source Code: [https://github.com/anandubajith/jiofi-plasmoid](https://github.com/anandubajith/jiofi-plasmoid)