Fix any DOCSIS/cable-modem connection issue in any country

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
User avatar
tj1010
Enthusiast
Enthusiast
Posts: 624
Joined: Mon Feb 25, 2013 5:51 pm
Location: US or Estonia
Contact:

Fix any DOCSIS/cable-modem connection issue in any country

Post by tj1010 »

Image

I used this tool to detect and replace a bad splitter and cable on my DOCSIS/cable internet/tv/phone connection. It monitors the standard 192.168.100.1 for bad dBmV and SNR values on both downstream and upstream and reports them along with tips for fixing.

compile thread-safe

Code: Select all

;DOCSIS/cable-modem diagnosis tool
If Not InitNetwork() : MessageRequester("Network Error","Unable to find active NIC") : End : EndIf

Declare diagnose()
Declare graphit(gadget.l,backcolor.l,downstream.l,upstream.l)
Declare monitor_modem(*val)

Structure powers
  power.f
  snr.f
  type.s
  modulation.s
EndStructure

Structure gstats
  ds.f
  us.f
EndStructure

Global Dim status.powers(0)
Global Dim stats.gstats(0)
Global url$="http://192.168.100.1/cgi-bin/status_cgi";you may need to change URI for your modem model
Global mthread.l=CreateThread(@monitor_modem(),1)

If OpenWindow(0,0,0,800,600,"DOCSIS Tech Tool 1.0",#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
  CanvasGadget(0,0,0,WindowWidth(0),((WindowHeight(0)*10)/100))
  EditorGadget(1,0,GadgetHeight(0)+3,WindowWidth(0),WindowHeight(0)-(GadgetHeight(0)+3),#PB_Editor_WordWrap)
  SetGadgetColor(1,#PB_Gadget_BackColor,RGB(0,0,0))
  SetGadgetColor(1,#PB_Gadget_FrontColor,RGB(183,246,7))
  Repeat
    event=WaitWindowEvent()
    gadget=EventGadget()
    type=EventType()
  Until event=#PB_Event_CloseWindow
EndIf

;delayed scraping of modem "tone" page
Procedure monitor_modem(*val)
  Repeat
    ReDim status(0)
    *buffer=ReceiveHTTPMemory(url$)
    If *buffer
      html$=PeekS(*buffer,MemorySize(*buffer),#PB_UTF8)
      FreeMemory(*buffer)
      If CountString(html$,"<html")>0 And CountString(html$,"dBmV")>0
        
        ;we got the page let's handle it
        Repeat
          start=FindString(html$,"dB",start)
          If start>0
            If Mid(html$,start,4)="dBmV"
              counter=start
              Repeat
                counter=counter-1
                If Mid(html$,counter,1)=">"
                  status(ArraySize(status()))\power=ValF(ReplaceString(Trim(Mid(html$,(counter+1),FindString(html$,"dBmV",(counter+1)))),"+",""))
                  Break
                EndIf
              ForEver
              ;set type
              If status(ArraySize(status()))\power<9.0 : status(ArraySize(status()))\type="downstream" : EndIf
              If status(ArraySize(status()))\power>10.0 : status(ArraySize(status()))\type="upstream" : EndIf
              ;set modulation
              If status(ArraySize(status()))\type = "upstream"
                If Mid(html$,FindString(html$,"TDMA",start)-1,5)="ATDMA"
                  status(ArraySize(status()))\modulation="ATDMA"
                Else
                  status(ArraySize(status()))\modulation="TDMA"
                EndIf
              EndIf
              ReDim status(ArraySize(status())+1)
            Else
              ;SNR field for current row
              counter=start
              Repeat
                counter=counter-1
                If Mid(html$,counter,1)=">"
                  status(ArraySize(status())-1)\snr=ValF(ReplaceString(Trim(Mid(html$,(counter+1),FindString(html$,"dB",(counter+1)))),"+",""))
                  Break
                EndIf
              ForEver
            EndIf
            start=start+1
          Else
            ;finished
            start=1
            Break
          EndIf
        ForEver
        ReDim status(ArraySize(status())-1)
        diagnose()
      Else
        AddGadgetItem(1,-1,"Network Error: Invalid data returned")
      EndIf
    Else
      AddGadgetItem(1,-1,"Network Error: Tone status page not found")
    EndIf
    Delay(10000)
  ForEver
EndProcedure

;small but dynamic graph to drop in anything. I'll do proper division average-set horizontal scaling later; vertical is fin
Procedure graphit(gadget.l,backcolor.l,downstream.l,upstream.l)
  Protected ld.l,lu.l
  StartDrawing(CanvasOutput(0))
  Box(0,0,GadgetWidth(gadget),GadgetHeight(gadget),backcolor)
  If ArraySize(stats()) < GadgetWidth(0) : timed=GadgetWidth(0)/ArraySize(stats()) : EndIf
  For i = 0 To ArraySize(stats())
    If i>0
      If Int(stats(i)\ds)>0 : LineXY((timed*(i-1)),GadgetHeight(gadget)-Int(ld),(timed*i),GadgetHeight(gadget)-Int(stats(i)\ds),downstream) : ld=stats(i)\ds : EndIf
      If Int(stats(i)\us)>0 : LineXY((timed*(i-1)),GadgetHeight(gadget)-Int(lu),(timed*i),GadgetHeight(gadget)-Int(stats(i)\us),upstream) : lu=stats(i)\us : EndIf 
    EndIf
    If i=0
      If Int(stats(i)\ds)>0 : LineXY(0,GadgetHeight(gadget)-Int(stats(i)\ds),timed,GadgetHeight(gadget)-Int(stats(i)\ds),downstream) : ld=stats(i)\ds : EndIf
      If Int(stats(i)\us)>0 : LineXY(0,GadgetHeight(gadget)-Int(stats(i)\us),timed,GadgetHeight(gadget)-Int(stats(i)\us),upstream) : lu=stats(i)\us : EndIf
    EndIf
  Next
  StopDrawing()
EndProcedure

;use collected data against common DOCSIS/cable-modem dBmV and SNR-dB diagnoses rules
;doesn't use fine-grain ranges based on frequency and modulation of upstream because it has been >45.0 on every ISP in every country I've been
Procedure diagnose()
  If ArraySize(status())>0
    ClearGadgetItems(1)
    AddGadgetItem(1,-1,"Updated: "+FormatDate("%hh:%ii:%ss",Date()))
    For i = 0 To ArraySize(status())
      If status(i)\type="upstream" And (status(i)\power>52.5 Or status(i)\power<45.0) : AddGadgetItem(1,-1,"Bad upstream power of "+StrF(status(i)\power,2)+" dBmV") : EndIf
      If status(i)\type="downstream" And (status(i)\power>15.0 Or status(i)\power<-15.0) : AddGadgetItem(1,-1,"Bad downstream power of "+StrF(status(i)\power,2)+" dBmV") : EndIf
      ;most firmwares don't display SNR for upstream channels
      If status(i)\type="downstream" And status(i)\snr<33.0 : AddGadgetItem(1,-1,"Bad downstream SNR of "+StrF(status(i)\snr,2)+" dB") : EndIf
    Next
    If CountGadgetItems(1)>1
      AddGadgetItem(1,-1,"TIP: Modem should be behind no more than one silver 1Ghz splitter without proper amplification before the first splitter")
      AddGadgetItem(1,-1,"TIP: All cable should be quad-shield RG6 for above-ground and quad-shield RG11 for buriel")
      AddGadgetItem(1,-1,"TIP: Cable/DOCSIS connections are effected by your neighbors equipment. DSL, Sat, Fiber, 4G are not")
      AddGadgetItem(1,-1,"TIP: Sometimes you'll show good status before internet fully restores this is the modem or OS registering DNS and DHCP")
      AddGadgetItem(1,-1,"TIP: If your ISP technician keeps working on the amp out at your drop or replacing modems it means there is bad equipment somewhere on your local infrastructure and they are trying to avoid the cost of fixing it while scamming you out of money")
    Else
      AddGadgetItem(1,-1,"All dBmV and downstream SNR levels are good")
    EndIf
  EndIf
  For i = 0 To ArraySize(status())
    AddGadgetItem(1,-1,status(i)\type+"   "+StrF(status(i)\power,2)+" dBmV   "+StrF(status(i)\snr,2)+" dB   "+status(i)\modulation)
    If status(i)\type="upstream" : stats(ArraySize(stats()))\us=((Int(status(i)\power)*GadgetHeight(0))/100) : EndIf
    If status(i)\type="downstream" : stats(ArraySize(stats()))\ds=((Int(status(i)\snr)*GadgetHeight(0))/100) : EndIf
    ReDim stats(ArraySize(stats())+1)
  Next
  ReDim stats(ArraySize(stats())-1)
  graphit(0,RGB(0,0,0),RGB(195,203,0),RGB(7,195,187))
EndProcedure
The truth hurts.