tomaae / homeassistant-mikrotik_router

Mikrotik router integration for Home Assistant
Apache License 2.0
301 stars 50 forks source link

[Feature] LTE modem cell info #249

Open sshalyminov opened 1 year ago

sshalyminov commented 1 year ago

Is it possible to implement cell info for LTE modem connected to router?

Here how to know lte interface:

[*@MikroTik] > /interface/lte/print 
Flags: R - RUNNING
Columns: NAME, MTU, NETWORK-MODE, APN-PROFILES
#   NAME   MTU  NETWORK-MODE  APN-PROFILES
0 R lte1  1500  3g            default     
                lte 

How to collect info:

[*@MikroTik] > /interface/lte/monitor lte1 once 
            status: connected
             model: EP06-E
          revision: EP06ELAR04A04M4G
  current-operator: 
    current-cellid: 134982913
            enb-id: 527277
         sector-id: 1
        phy-cellid: 249
        data-class: LTE
    session-uptime: 6h57m15s
              imei: [cutted]
              imsi: [cutted]
              uicc: [cutted]
      primary-band: B3@15Mhz earfcn: 1725 phy-cellid: 249
              rssi: -54dBm
              rsrp: -85dBm
              rsrq: -12dB
              sinr: 26dB

For me interesting next sensors: for interface sensors: current-cellid (numeric) enb-id (numeric) sector-id (numeric) phy-cellid (numeric) data-class (text) session-uptime (timestamp) primary-band (text) ca-band (text, in my example earlier it is not exist because of my cell does not support aggregation, but for future and another places) rssi (numeric) rsrp (numeric) rsrq (numeric) sinr (numeric)

This can help to monitor connection stability and quality.

Thank you!

sshalyminov commented 1 year ago

How it looks in WinBox: image

tomaae commented 1 year ago

I can see how this would help, but I dont have any LTE modem to test work on this. Monitor commands can be tricky. Will try to ask around if somebody has one that I can use for a day.

sshalyminov commented 1 year ago

If you need any debug - no problem, I can do this for you.

tomaae commented 1 year ago

that wont work unfortunatly. api is not fully documented so I dont know interface attribute name for monitor command. it will require lot of trial and error work just to get to debug output I need to implement this functionality.

sshalyminov commented 1 year ago

/interface/lte/print will show you all lte interfaces - see firs output in my initial message

tomaae commented 1 year ago

thats not what I mean. that part is simple and will work. monitor needs a parameter, api works different compared to command line

tomaae commented 1 year ago

I'm not able to get one. can you recommend something? if I can get it cheap, I will consider it.

sshalyminov commented 1 year ago

Better to ask your cell operator. Here simpliest LTE modem cost is around $40. You can find much cheaper on Aliexpress if you use it.

tomaae commented 1 year ago

Unfortunatly, all offers I got are way more I'm willing to put into something I most likely wont ever use. So there are really only few options:

  1. You can give me api access to your device. This of course involves exposing api to internet, so there may be a risk involved.
  2. Get me an LTE capable device compatible with one of my devices
  3. Try to add the functionality on your own
sshalyminov commented 1 year ago

Using API client from https://github.com/DEssMALA/RouterOS_API I've got next:

API command: /interface/lte/print output: [{'.id': '*6', 'default-name': 'lte1', 'name': 'lte1', 'mtu': '1500', 'apn-profiles': 'default', 'allow-roaming': 'false', 'network-mode': '3g,lte', 'band': '', 'running': 'true', 'disabled': 'false'}]

Here we can take interface name from "name" field.

API command:

/interface/lte/monitor
=numbers=lte1
=once=

Output: [{'status': 'connected', 'model': 'EP06-E', 'revision': 'EP06ELAR04A04M4G', 'current-operator': '', 'current-cellid': '134982913', 'enb-id': '527277', 'sector-id': '1', 'phy-cellid': '249', 'data-class': 'LTE', 'session-uptime': '3d14h25m28s', 'imei': '***', 'imsi': '***', 'uicc': '***', 'primary-band': 'B3@15Mhz earfcn: 1725 phy-cellid: 249', 'rssi': '-63', 'rsrp': '-89', 'rsrq': '-7', 'sinr': '22'}]

I've removed imei, imsi and uicc manually from output. So as you see all fields are available (except ca-band as I mentioned earlier because of limitation of my current cell).

Is this enough for implementation? I can test your changes on my installation. I'm not sure I have ability to change your code to implement it by myself - it will required lot of time to understand how you doing things. I can't open API for you because of do not have "white IP", my cell operator gives us IP under it's NAT.

tomaae commented 1 year ago

Thats wont help me much, since I need to know how to access it. That API uses something custom, as "numbers" field does not exist. You can try adding this somewhere, for example on top of get_interface function.

_LOGGER.error(self.api.query(
                    "/interface/lte",
                    command="monitor",
                    args={".id": 6, "once": True},
                ))

My guess this should give a response if it is working like most command queries. No need to run debug, it will show as error, to make things easier.

Also, which information from both print and monitor is important to have in HA? I never used custom LTE, so I would be guessing.

sshalyminov commented 1 year ago

Added as next lines after def get_interface(self): in mikrotik_controller.py file.

Command:

        _LOGGER.error(self.api.query(
                    "/interface/lte",
                    command="print",
                    args={},
                ))

Error in log with answer:

Logger: custom_components.mikrotik_router.mikrotik_controller
Source: custom_components/mikrotik_router/mikrotik_controller.py:743
Integration: Mikrotik Router ([documentation](https://github.com/tomaae/homeassistant-mikrotik_router), [issues](https://github.com/tomaae/homeassistant-mikrotik_router/issues))
First occurred: 15:55:17 (1 occurrences)
Last logged: 15:55:17

[{'.id': '*6', 'default-name': 'lte1', 'name': 'lte1', 'mtu': 1500, 'apn-profiles': 'default', 'allow-roaming': False, 'network-mode': '3g,lte', 'band': '', 'running': True, 'disabled': False}]

Command:

        _LOGGER.error(self.api.query(
                    "/interface/lte",
                    command="monitor",
                    args={".id": 6, "once": True},
                ))

Error in log is "None" and secondary error from mikrotik api is "item not found"

Then command argument changed to:

        _LOGGER.error(self.api.query(
                    "/interface/lte",
                    command="monitor",
                    args={".id": 0, "once": True},
                ))

And this gives answer:

Logger: custom_components.mikrotik_router.mikrotik_controller
Source: custom_components/mikrotik_router/mikrotik_controller.py:743
Integration: Mikrotik Router ([documentation](https://github.com/tomaae/homeassistant-mikrotik_router), [issues](https://github.com/tomaae/homeassistant-mikrotik_router/issues))
First occurred: 15:45:17 (2 occurrences)
Last logged: 15:46:09

[{'status': 'connected', 'model': 'EP06-E', 'revision': 'EP06ELAR04A04M4G', 'current-operator': '', 'current-cellid': 134982913, 'enb-id': 527277, 'sector-id': 1, 'phy-cellid': 249, 'data-class': 'LTE', 'session-uptime': '4d4h51m45s', 'imei': ****, 'imsi': ***, 'uicc': '***', 'primary-band': 'B3@15Mhz earfcn: 1725 phy-cellid: 249', 'rssi': -60, 'rsrp': -88, 'rsrq': -10, 'sinr': 22}]
[{'status': 'connected', 'model': 'EP06-E', 'revision': 'EP06ELAR04A04M4G', 'current-operator': '', 'current-cellid': 134982913, 'enb-id': 527277, 'sector-id': 1, 'phy-cellid': 249, 'data-class': 'LTE', 'session-uptime': '4d4h52m38s', 'imei': ***, 'imsi': ***, 'uicc': '***', 'primary-band': 'B3@15Mhz earfcn: 1725 phy-cellid: 249', 'rssi': -57, 'rsrp': -88, 'rsrq': -12, 'sinr': 24}]

I don't know why id is not same as in "print" command, probably it's re-numerated in monitor? And need to enum interfaces from "print" command from 0 incrementally if few interfaces available? I don't have secondary modem to check.

Regarding information - I've already listed it earlier, for me interesting: status (boolean, connected or not) current-cellid (integer) enb-id (integer) sector-id (integer) phy-cellid (integer) data-class (string) session-uptime (timestamp? or string at least for later parsing) primary-band (string) ca-band (string) (if available, otherwise 'None') rssi (integer, dBm) rsrp (integer, dBm) rsrq (integer, dB) sinr (integer, dB)

Also "name" from "print" command may be used as interface name. And "model" from "monitor" as additional information for device (description?) if you provide it.

tomaae commented 1 year ago

Yea, thats really weird behaviour. ".id" should be exact match for interface ".id". Could be a bug, or maybe something that is not implemented in this command. But at least we have a response, which is good.

what if you try:

        _LOGGER.error(self.api.query(
                    "/interface/lte",
                    command="monitor",
                    args={".id": "lte1", "once": True},
                ))

if that works, change lte1 to something that does not exist to see if you get error.

it could also be

        _LOGGER.error(self.api.query(
                    "/interface/lte",
                    command="monitor",
                    args={"name": "lte1", "once": True},
                ))

or default-name instead of name

Also, is current-operator really empty, or did you just removed it?

Also 2, what are you looking to do with this functionality/how do you plan to use it?

sshalyminov commented 1 year ago
        _LOGGER.error(self.api.query(
                    "/interface/lte",
                    command="monitor",
                    args={".id": "lte1", "once": True},
                ))

This one working excellent, all info returned. Others generate error "unknown parameter"

sshalyminov commented 1 year ago

Also, is current-operator really empty, or did you just removed it?

Empty. Probably firmware just don't know my operator code/name :)

Also 2, what are you looking to do with this functionality/how do you plan to use it?

I wrote at beginning - monitor stability of channel. Week ago my closest cell breaks and I had 2 days of fun looking in WinBox how modem tried find another ways to connect - changed LTE/3G protocols, changed channels and other things. Especially interesting rssi/rsrp/rsrq/sinr in a case if you want to adjust antenna position to find best signal. And rest things :)

Of course I can see all of this in WinBox, but HA is much interesting in sight of statistics, for example how signal changing depends on weather conditions - may be much better to setup antenna to less powerful cell station but more stable instead of powerful one but with unstable signal.

sshalyminov commented 1 year ago

if that works, change lte1 to something that does not exist to see if you get error.

Forget to add - if I set ".id" anything else than 0 or 'lte1' - I've got error "item not found" - I had same when ".id" was set to 6 earlier if you remember.

tomaae commented 1 year ago

thanks, I just need one more thing.

'default-name': 'lte1', 'name': 'lte1'

Can you temporary rename the interface to anything else and test it again? I need to know if monitor it is accepting 'default-name' or 'name' as a parameter. could be actually both, but it is important to know this one.

sshalyminov commented 1 year ago

Renamed to lte1m

        _LOGGER.error(self.api.query(
                    "/interface/lte",
                    command="print",
                    args={},
                ))
[{'.id': '*6', 'default-name': 'lte1', 'name': 'lte1m', 'mtu': 1500, 'apn-profiles': 'default', 'allow-roaming': False, 'network-mode': '3g,lte', 'band': '', 'running': True, 'disabled': False}]

        _LOGGER.error(self.api.query(
                    "/interface/lte",
                    command="monitor",
                    args={".id": "lte1m", "once": True},
                ))
[{'status': 'connected', 'model': 'EP06-E', 'revision': 'EP06ELAR04A04M4G', 'current-operator': '', 'current-cellid': 134982913, 'enb-id': 527277, 'sector-id': 1, 'phy-cellid': 249, 'data-class': 'LTE', 'session-uptime': '4d10h57m14s', 'imei': ***, 'imsi': ***, 'uicc': '***', 'primary-band': 'B3@15Mhz earfcn: 1725 phy-cellid: 249', 'rssi': -57, 'rsrp': -88, 'rsrq': -10, 'sinr': 24}]
tomaae commented 1 year ago

ok, so it takes "name". thanks, thats all I needed for implementation.

mimiromik commented 1 year ago

Hi. Is information logging already integrated? Or I have to put it manually in "mikrotik_controller.py" Could I ask for a summary of the entire embed code and its modifications? I would also like to monitor the connection quality of my Mikrotik " RBLHGR & R11e-4G". Thank you.

heikkimu commented 1 year ago

+1 for this. It’s really useful in adjusting the entennas in optimal position.

I could also lend a hand, I’ve a mikrotik lte rhg r and I’m proficient with Python.

Here’s my current network tab in HA.

7B374A8F-827C-473E-971C-5CFE5A64495D

mimiromik commented 1 year ago

+1 for this. It’s really useful in adjusting the entennas in optimal position.

I could also lend a hand, I’ve a mikrotik lte rhg r and I’m proficient with Python.

Here’s my current network tab in HA.

Very nice. It looks exactly as I would like it to. Could you please share your knowledge. And write what and where to put it?

heikkimu commented 1 year ago

@mimiromik for Huwei I’m just using the default HA-integration and it shows also the signal qualityparameters.

for plotting, I’ve used histogram. For speed testing and ping I used speedtest-integration.

mimiromik commented 1 year ago

@heikkimu Who is talking about Huawei? The topic is about MikroTik. And it does not offer the necessary values ​​in integration.

acidsas commented 1 year ago

@tomaae I can give you remote access to Mikrotiks with different LTE modems. Mail me — acidsas at gmail.com

hertzg commented 1 year ago

This is my current setup with 2 LTE dishes (LHG & ATL), I've been following this thread for some time and managed to get this working without the integration, just using the new REST api from ROS.

image

rest:
- resource: https://lte1.redacted/rest/interface/lte/monitor
  verify_ssl: true
  authentication: basic
  username: !secret mikrotik_username
  password: !secret mikrotik_password
  method: POST
  headers:
    "content-type": "application/json"
  payload: |
    {"numbers": "lte1", "once": true, "without-paging": true}
  scan_interval: 3
  sensor:
    - unique_id: "mikrotikRest_lhggmlte18_lte1_dataClass"
      name: "LHGGMLTE18 lte1 Data-Class"
      value_template: "{{ value_json.0['data-class'] }}"

    - unique_id: "mikrotikRest_lhggmlte18_lte1_status"
      name: "LHGGMLTE18 lte1 Status"
      value_template: "{{ value_json.0['status'] }}"

    - unique_id: "mikrotikRest_lhggmlte18_lte1_cqi"
      name: "LHGGMLTE18 lte1 CQI"
      state_class: measurement
      value_template: "{{ value_json.0['cqi'] | int }}"

    - unique_id: "mikrotikRest_lhggmlte18_lte1_ri"
      name: "LHGGMLTE18 lte1 RI"
      state_class: measurement
      value_template: "{{ value_json.0['ri'] | int }}"

    - unique_id: "mikrotikRest_lhggmlte18_lte1_mcs"
      name: "LHGGMLTE18 lte1 MCS"
      state_class: measurement
      value_template: "{{ value_json.0['mcs'] | int }}"

    - unique_id: "mikrotikRest_lhggmlte18_lte1_rsrp"
      name: "LHGGMLTE18 lte1 RSRP"
      device_class: "signal_strength"
      unit_of_measurement: "dBm"
      state_class: measurement
      value_template: "{{ value_json.0['rsrp'] | int }}"

    - unique_id: "mikrotikRest_lhggmlte18_lte1_rsrq"
      name: "LHGGMLTE18 lte1 RSRQ"
      device_class: "signal_strength"
      unit_of_measurement: "dB"
      state_class: measurement
      value_template: "{{ value_json.0['rsrq'] | int }}"

    - unique_id: "mikrotikRest_lhggmlte18_lte1_rssi"
      name: "LHGGMLTE18 lte1 RSSI"
      device_class: "signal_strength"
      unit_of_measurement: "dBm"
      state_class: measurement
      value_template: "{{ value_json.0['rssi'] | int }}"

    - unique_id: "mikrotikRest_lhggmlte18_lte1_sinr"
      name: "LHGGMLTE18 lte1 SINR"
      device_class: "signal_strength"
      unit_of_measurement: "dB"
      state_class: measurement
      value_template: "{{ value_json.0['sinr'] | int }}"

    - unique_id: "mikrotikRest_lhggmlte18_lte1_currentCellId"
      name: "LHGGMLTE18 lte1 Current Cell ID"
      value_template: "{{ value_json.0['current-cellid'] | int }}"

    - unique_id: "mikrotikRest_lhggmlte18_lte1_eNBId"
      name: "LHGGMLTE18 lte1 eNB ID"
      value_template: "{{ value_json.0['enb-id'] | int }}"

    - unique_id: "mikrotikRest_lhggmlte18_lte1_sectorId"
      name: "LHGGMLTE18 lte1 Sector ID"
      value_template: "{{ value_json.0['sector-id'] | int }}"

    - unique_id: "mikrotikRest_lhggmlte18_lte1_currentOperator"
      name: "LHGGMLTE18 lte1 Current Operator"
      value_template: "{{ value_json.0['current-operator'] }}"

config is the same for LTE2 as well