import times, posix, osproc, utils import asyncHttpServer proc prometheusResponse* (request: Request, state: JsonNode) {.async.} = var res = "" if state["inetstat"]["lastUpdated"].getInt == 0 and state["mobiled"]["lastUpdated"].getInt == 0: await request.respond(Http500, "500 No data yet", newHttpHeaders([("Content-Type","text/plain")])) if state["inetstat"]["lastUpdated"].getInt != 0: let data = state["inetstat"]["data"] let lastUpdated = state["inetstat"]["lastUpdated"].getInt if data.hasKey("Total0"): #total res &= "fritzbox_network_transmit_bytes_total " & $(data.getTxTraffic("Total0")) & " " & $(lastUpdated * 1000) & "\n" res &= "fritzbox_network_receive_bytes_total " & $(data.getRxTraffic("Total0")) & " " & $(lastUpdated * 1000) & "\n" #month res &= "fritzbox_network_transmit_bytes_month " & $(data.getTxTraffic("ThisMonth0")) & " " & $(lastUpdated * 1000) & "\n" res &= "fritzbox_network_receive_bytes_month " & $(data.getRxTraffic("ThisMonth0")) & " " & $(lastUpdated * 1000) & "\n" #today res &= "fritzbox_network_transmit_bytes_today " & $(data.getTxTraffic("Today0")) & " " & $(lastUpdated * 1000) & "\n" res &= "fritzbox_network_receive_bytes_today " & $(data.getRxTraffic("Today0")) & " " & $(lastUpdated * 1000) & "\n" if state["mobiled"]["lastUpdated"].getInt != 0: let data = state["mobiled"]["data"] let lastUpdated = state["mobiled"]["lastUpdated"].getInt() if data.hasKey("ue0"): if data["ue0"].hasKey("temperature") and data["ue0"]["temperature"].getInt != 0: res &= "fritzbox_temperature " & $(data["ue0"]["temperature"].getInt/1000) & " " & $(lastUpdated * 1000) & "\n" if data["ue0"].hasKey("conn_rate_rx"): let downstream = data["ue0"]["conn_rate_rx"].getInt() res &= "fritzbox_network_downstram " & $(downstream) & " " & $(lastUpdated * 1000) & "\n" if data["ue0"].hasKey("conn_rate_tx"): let upstream = data["ue0"]["conn_rate_tx"].getInt() res &= "fritzbox_network_upstream " & $(upstream) & " " & $(lastUpdated * 1000) & "\n" if data["ue0"].hasKey("conn_cell"): template parseCell(data: JsonNode, num: int) = let cells = data["ue0"]["conn_cell"].getStr.split(",") if cells[num] != "" and data.hasKey("cell"&cells[num]): let cell = "cell"&cells[num] if data[cell].hasKey("cell_type"): let cell_technology = data[cell]["cell_type"].getStr let tech_id = %* { "umts": 3, "lte": 4 } res &= "fritzbox_cell_techology{cell=\"" & $num & "\"} " & $(tech_id[cell_technology].getInt) & " " & $(lastUpdated * 1000) & "\n" if data[cell].hasKey("quality"): let cell_quality = data[cell]["quality"].getInt res &= "fritzbox_network_quality{cell=\"" & $num & "\"} " & $(cell_quality) & " " & $(lastUpdated * 1000) & "\n" if data[cell].hasKey("band"): let cell_band = data[cell]["band"].getInt res &= "fritzbox_network_band{cell=\"" & $num & "\"} " & $(cell_band) & " " & $(lastUpdated * 1000) & "\n" if data[cell].hasKey("distance"): let cell_distance = data[cell]["distance"].getInt res &= "fritzbox_network_distance{cell=\"" & $num & "\"} " & $(cell_distance/1000) & " " & $(lastUpdated * 1000) & "\n" if data[cell].hasKey("usage"): let cell_usage = data[cell]["usage"].getInt res &= "fritzbox_network_usage{cell=\"" & $num & "\"} " & $(cell_usage) & " " & $(lastUpdated * 1000) & "\n" data.parseCell(0) data.parseCell(1) await request.respond(Http200, res, newHttpHeaders([("Content-Type","text/plain")])) proc statusResponse* (request: Request, state: JsonNode) {.async.} = var res = "" var responseJson = %* { "traffic": { "lastUpdated": 0, "total": { "received": 0, "transmited": 0, }, "month": { "received": 0, "transmited": 0, }, "today": { "received": 0, "transmited": 0, } }, "modem": { "lastUpdated": 0, "connectedCells": [] } } if state["inetstat"]["lastUpdated"].getInt == 0 and state["mobiled"]["lastUpdated"].getInt == 0: await request.respond(Http500, "500 No data yet", newHttpHeaders([("Content-Type","text/plain")])) if state["inetstat"]["lastUpdated"].getInt != 0: let data = state["inetstat"]["data"] responseJson["traffic"]["lastUpdated"] = state["inetstat"]["lastUpdated"] if data.hasKey("Total0"): #total responseJson["traffic"]["total"]["transmited"] = %data.getTxTraffic("Total0") responseJson["traffic"]["total"]["received"] = %data.getRxTraffic("Total0") #month responseJson["traffic"]["month"]["transmited"] = %data.getTxTraffic("ThisMonth0") responseJson["traffic"]["month"]["received"] = %data.getRxTraffic("ThisMonth0") #today responseJson["traffic"]["today"]["transmited"] = %data.getTxTraffic("Today0") responseJson["traffic"]["today"]["received"] = %data.getRxTraffic("Today0") if state["mobiled"]["lastUpdated"].getInt != 0: let data = state["mobiled"]["data"] responseJson["modem"]["lastUpdated"] = state["mobiled"]["lastUpdated"] if data.hasKey("ue0"): if data["ue0"].hasKey("temperature") and data["ue0"]["temperature"].getInt != 0: responseJson["modem"]["temperature"] = %(data["ue0"]["temperature"].getInt/1000) if data["ue0"].hasKey("spn"): responseJson["modem"]["vendorText"] = data["ue0"]["spn"] if data["ue0"].hasKey("conn_rate_rx"): responseJson["modem"]["linkSpeedRx"] = data["ue0"]["conn_rate_rx"] if data["ue0"].hasKey("conn_rate_tx"): responseJson["modem"]["linkSpeedTx"] = data["ue0"]["conn_rate_tx"] if data["ue0"].hasKey("conn_cell"): proc parseCell(data: JsonNode, num: int):JsonNode = let cells = data["ue0"]["conn_cell"].getStr.split(",") result = %* {} let cell = "cell"&cells[num] if cells[num] != "" and data.hasKey(cell): if data[cell].hasKey("cell_type"): result["technology"] = data[cell]["cell_type"] if data[cell].hasKey("provider"): result["provider"] = data[cell]["provider"] if data[cell].hasKey("plmn"): result["plmn"] = data[cell]["plmn"] if data[cell].hasKey("plmn"): result["plmn"] = data[cell]["plmn"] if data[cell].hasKey("cell_id"): result["cellId"] = data[cell]["cell_id"] if data[cell].hasKey("rssi"): result["rssi"] = %data[cell]["rssi"] if data[cell].hasKey("rscp"): result["rscp"] = %data[cell]["rscp"] if data[cell].hasKey("rsrp"): result["rsrp"] = %data[cell]["rsrp"].getStr.split(",")[0] if data[cell].hasKey("rsrq"): result["rsrq"] = %data[cell]["rsrq"].getStr.split(",")[0] if data[cell].hasKey("sinr"): result["sinr"] = %data[cell]["sinr"].getStr.split(",")[0] if data[cell].hasKey("quality"): result["quality"] = data[cell]["quality"] if data[cell].hasKey("band"): result["band"] = data[cell]["band"] if data[cell].hasKey("usage"): result["usage"] = data[cell]["usage"] if data[cell].hasKey("distance"): result["distance"] = data[cell]["distance"] responseJson["modem"]["connectedCells"].add(data.parseCell(0)) responseJson["modem"]["connectedCells"].add(data.parseCell(1)) await request.respondJson(Http200, "success", "", responseJson) proc main = # for gcsafe setControlCHook(CtrlCHook) onSignal(SIGTERM): echo "Got SIGTERM! \nStopping Server now!" quit() let authToken = "penis123" var server = newServer("0.0.0.0", 1234) # launch on http://localhost:5000 var state = %* { "inetstat": { "data": {}, "lastUpdated": 0, }, "mobiled": { "data": {}, "lastUpdated": 0, } } proc timerProc() = let inetstat_data = execProcess("/usr/bin/ctlmgr_ctl u inetstat") let mobiled_data = execProcess("/usr/bin/ctlmgr_ctl u mobiled") state["inetstat"]["data"] = parseCtlMgr(inetstat_data) state["inetstat"]["lastUpdated"] = %toUnix(getTime()) state["mobiled"]["data"] = parseCtlMgr(mobiled_data) state["mobiled"]["lastUpdated"] = %toUnix(getTime()) addTimer(10000, false, proc(fd: AsyncFD): bool = timerProc() ) timerProc() server.pages: equals("/"): await request.respond(Http200, "Hello, nothing to see here", newHttpHeaders([("Content-Type","text/plain")])) equals("/metrics"): await request.prometheusResponse(state) equals("/status.json"): await request.statusResponse(state) equals("/inetstat.json"): if state["inetstat"]["lastUpdated"].getInt != 0: await request.respondJson(Http200, "success", "", state["inetstat"]["data"]) else: await request.respondJson(Http404, "error", "no data yet", newJObject()) equals("/mobiled.json"): if state["mobiled"]["lastUpdated"].getInt != 0: await request.respondJson(Http200, "success", "", state["mobiled"]["data"]) else: await request.respondJson(Http404, "error", "no data yet", newJObject()) server.start() main()