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