[SOLVED] Parse Xml data on Huawei Lte router to display montly data usage

Good morning to the whole community. I have a problem. I would like to create a timer function that reads the APIs of a Huawei LTE router to monitor and display the monthly consumption of data in HabPanel. On the internet I found this code in pyton at this link: https://www.mrt-prodz.com/blog/view/2015/05/huawei-modem-api-and-data-plan-monitor[https://www.mrt-prodz.com/blog/view/2015/05/huawei-modem-api-and-data-plan-monitor]

#!/usr/bin/env python
import urllib2, xml.etree.ElementTree as ET

MODEM_IP = '192.168.1.1'
API_PATH = '/api/'

# retrieve xml and if successful return root
def get_xml_root(api_call):
        try:
                xmlobj = urllib2.urlopen('http://'+MODEM_IP+API_PATH+api_call)
        except:
                print '[!] Error while making GET request for', api_call
                exit(1)
        return ET.parse(xmlobj).getroot()

# return value in specified xml tag
def get_value(root, tag):
        value = root.find(tag)
        if value is not None:
                return value.text
        else:
                print '[!] Error while retrieving value of', tag
                exit(1)

# return data plan usage percentage
def get_usage():
        # modem will not allow API calls if someone is logged in
        root = get_xml_root('user/state-login')
        state = int(get_value(root, 'State'))
        user = get_value(root, 'Username')
        # if state is -1 and username is not empty we cannot make the API call
        if (state == -1) and (user is not None):
                print '[!] Cannot make API calls: %s is logged in' % user
                exit(1)

        # retrieve download and upload traffic and convert them to MB
        root = get_xml_root('monitoring/month_statistics')
        month_download = int(int(get_value(root, 'CurrentMonthDownload'))/1048576)
        month_upload = int(int(get_value(root, 'CurrentMonthUpload'))/1048576)

        # retrieve data plan limit and convert to MB
        root = get_xml_root('monitoring/start_date')
        data_limit = get_value(root, 'DataLimit')

        # convert DataLimit suffix GB to MB
        if data_limit[2:] == 'GB':
                data_limit = int(data_limit[:-2])*1024
        else:
                data_limit = int(data_limit[:-2])

        # return percentage
        return int(round((float(month_upload + month_download) / data_limit) * 100))


print 'DATA PLAN USAGE: {0}%'.format(get_usage())
And here is the output when calling the script:

mrt:~/huawei/mirror/example$ ./get_usage.py

DATA PLAN USAGE: 71%

But I have no idea how to use it. Bindings to install or Rules to create. Openhab use in Windows with Karaf. Can you give me an idea on the easiest method to use?
Thank you all

One option would be to use the Exec Binding and call this external script to populate a String Item in OH2. You would need to install python on Windows for this script to run.

On the other hand, this seems too cumbersome for me…
Does the Router offer snmp? Polling the correct OID would be simpler.

edit1: no, it doesn’t have snmp :frowning: https://consumer.huawei.com/nz/mobile-broadband/e5220/specs/

edit2: It offers web api, so you can also use the HTTP Binding and some transformation to pull specific data from it. https://www.mrt-prodz.com/blog/view/2015/05/huawei-modem-api-and-data-plan-monitor

Meanwhile, thanks for the reply. From what I understand, he has no snmp. In fact, installing pyton is not a big deal, and http binding may also be a solution, but I do not know where to start in either case. This morning I tried to use Regex transformation in this way in an item:

String Huawey	  "Huawey [%s]"	 {http="<[http://192.127.0.1/api/monitoring/month_statistics:CurrentMonthDownload:60000:REGEX((.*?))]"}

But as a response I get only the first part of the XML with an error code.

Which is, in your opinion, the easiest way to try to go for a newbie?

I would try HTTP Binding with the XPath Transformation Service

something like (warning: untested):

String Huawey	  "Huawey [%s]"	 {http="<[http://192.127.0.1/api/monitoring/month_statistics:60000:XPATH(/response/CurrentMonthDownload/text())]"}

Read more on XPath on the docs and search the forum for examples.

You can also try the python pre-made script using the Exec Binding to get the data plan usage as a Percent.

Great. Thank you very much. I try and let you know.

1 Like

No way. After 6 hours of tests, I get no answers or errors if an XPath.
Instead with REGEX I get an answer. But the answer is the error code for an unauthorized user. I have done several tests like:

String Test2	"Test2 [%s]"  {http="<[http://admin:password@192.127.0.1/api/monitoring/month_statistics:60000:REGEX(.*?<CurrentMonthDownload>(.*?)</CurrentMonthDownload>.*)]"}

But I can not go any further.
In the meantime I installed pyton and I’m trying to get the script to run with EXEC Binding

read how to authenticate using the HTTP binding (you can’t use user:pass@ … you need to use Basic Auth)

String Huawey	  "Huawey [%s]"	 {http="<[http://192.127.0.1/api/monitoring/month_statistics{Authorization=Basic YWRtaW46cGFzc3dvcmQ=}:60000:XPATH(/response/CurrentMonthDownload/text())]"}

Converted admin:password to YWRtaW46cGFzc3dvcmQ= using https://www.base64encode.org/

Sorry. In fact I had not specified in the previous post. I had already done the test with the Basic Auth, and in this way I do not get any answer, not even the error code. Nothing in logs. I have also tried to install different Tranformation Bindings: RegEx, Xpath and JsonPath.
But I noticed something. If I enter the API string from the browser (192.127.0.1/api/monitoring/month_statistics) I get the same error. I must first view the main page (http://192.127.0.1/html/home.html) and then call the bees. in this way, the browser displays me the correct data. As for OH, the fact of being logged by browser or not, makes no difference. I think the only way is using the Pyton script but for now it is not possible.
I’m sorry I can not use the declaration in the item with Transformation, because it was a more elegant and clean solution.

Goodmorning everyone. Good news. I did it with RegEx transformation like this:

Number CM_Download	"Download [%s]"  	{http="<[http://192.127.0.1/api/monitoring/month_statistics{Authorization=Basic YWRtaW46TWFsbGVvMTc=}:600000:REGEX(.*?<CurrentMonthDownload>(.*?)</CurrentMonthDownload>.*)]"}
Number CM_Upload  	"Upload  [%s]"	 	{http="<[http://192.127.0.1/api/monitoring/month_statistics{Authorization=Basic YWRtaW46TWFsbGVvMTc=}:600000:REGEX(.*?<CurrentMonthUpload>(.*?)</CurrentMonthUpload>.*)]"}

then I created a rules where I transform data into GB and report them to my monthly plan which has a limit of 200gb

rule "modem"

when   
	Item CM_Download received update  or System started
then 
	
 	Download_Gb.postUpdate((CM_Download.state as DecimalType) / 1048576000)
	Upload_Gb.postUpdate((CM_Upload.state as DecimalType) / 1048576000)
	Lte_Usage_Absolute.postUpdate((Download_Gb.state as DecimalType) + (Upload_Gb.state as DecimalType))
Lte_Usage_Perc.postUpdate((((Download_Gb.state as DecimalType) + (Upload_Gb.state as DecimalType)) / 200) * 100)

			
end

so I can see both monthly use as an absolute value and as a percentage. Thanks for the availability and good OH to everyone waiting for you to arrive here in Italy!

1 Like