func main() gconst FileChannel 1 global IP as string global Port as integer global Run as integer global Raw as integer Run = 0 Raw = 0 print "Loconet Monitor V0.1" print "(c) Michael Mosher 2007" print " " print "Requires Loconet over TCP server" print " " if FileInfo(".\IP.dat",2) = "True" then IP = FileQuickLoad(".\IP.dat") print "load IP " + IP else IP = "127.0.0.1" print "defualt IP " + IP endif if FileInfo(".\Port.dat",2) = "True" then Port = FileQuickLoad(".\Port.dat") print "load Port " + Port else Port = 1234 print "defualt Port " + Port endif Main_DisplayForm() LoopMain: if FormAllButtons() = 1 then if FormButton(Button_Quit,0) > 0 then '------ Quit Handler ----- End endif if FormButton(Button_Start,0) > 0 then '------ Start Handler ----- IP = FormTextBox(Text_IP) Port = FormTextBox(Text_Port) if ConnectTCP() = 0 then Run = 1 endif endif if FormButton(Button_Stop,0) > 0 then '------ Stop Handler ----- Run = 0 SocketClose(1) endif if FormButton(Button_FullSrn,0) > 0 then '------ Full Screen Console Handler ----- Console(3) endif if FormButton(Button_Save,0) > 0 then '------ Save Handler ----- IP = FormTextBox(Text_IP) Port = FormTextBox(Text_Port) FileQuickSave(".\IP.dat", IP) FileQuickSave(".\Port.dat", Port) endif if FormButton(Button_File,0) > 0 then '------ File Handler ----- DecodeFile() endif if FormButton(Button_Raw,0) > 0 then '------ Raw Handler ----- if Raw = 0 then Raw = 1 print "Raw on" FormBrush(255,255,0) else Raw = 0 print "Raw off" FormBrush(128,128,0) endif FormFillRectangle(141,136,5,18) endif endif if Run = 1 then DecodeTCP() endif Goto LoopMain endfunc '------------------------------------------------------------------------------- func DecodeTCP() dim i, Status as integer dim Buffer as string dim Line as string dim Token as string Token = chr(13)+chr(10) if SocketBuff(1) > 0 then Buffer = SocketInput(1) i = 1 LoopDecodeTCP: Line = GetWord(Buffer, 1, i, Token, Status) if Status <> -1 then if BeginsWith(Line, "RECEIVE") = 1 then Decode(Mid(Line,8,Len(Line)-10))) endif i = i + 1 goto LoopDecodeTCP endif endif endfunc '------------------------------------------------------------------------------- func ConnectTCP() as integer TimerClear(1) SocketConnect(1,IP,Port) WaitLoop: if SocketState(1) = 4 then print "Connected" exit(0) else print "Waiting.... "+SocketData(1,6)+" / "+SocketData(1,5) endif pause(100) if Timer(1) > 30000 then MsgBox("Can't Connect", 0) exit(1) endif Goto WaitLoop endfunc '------------------------------------------------------------------------------- func Decode(Line as string) dim i, j, bit, x, Decoded, Count, Bytes, Hours, Minutes, FracMins as integer dim Status as integer dim ByteString as string dim Byte(20) as integer dim Address, Data, CV as integer if Raw = 1 then print Line Decoded = 0 i = 0 Loop: ByteString = GetWord(Line, 1, i+1, " ", Status) Byte(i) = HexToDec(ByteString) if Status <> -1 then i = i + 1 goto Loop endif if Byte(0) = $81 then 'Busy print "Busy" Decoded = 1 endif if Byte(0) = $82 then 'GPOFF print "Global Power Off" Decoded = 1 endif if Byte(0) = $83 then 'GPON print "Global Power On" Decoded = 1 endif if Byte(0) = $85 then 'Idle print "Force Idle, Broadcast E-Stop" Decoded = 1 endif if Byte(0) = $A0 then 'Loco Speed print "Slot " + Byte(1) + " to speed " + Byte(2) Decoded = 1 endif if Byte(0) = $A1 then 'Loco Dir/F0-F4 print "Slot " + Byte(1); if BitGet(Byte(2),5) = 1 then print " Rev"; else print " For"; endif if BitGet(Byte(2),4) = 1 then print " F0 on"; else print " F0 off"; endif if BitGet(Byte(2),0) = 1 then print " F1 on"; else print " F1 off"; endif if BitGet(Byte(2),1) = 1 then print " F2 on"; else print " F2 off"; endif if BitGet(Byte(2),2) = 1 then print " F3 on"; else print " F3 off"; endif if BitGet(Byte(2),3) = 1 then print " F4 on" else print " F4 off" endif Decoded = 1 endif if Byte(0) = $A2 then 'Loco F5-F8 print "Slot " + Byte(1); if BitGet(Byte(2),0) = 1 then print " F5 on"; else print " F5 off"; endif if BitGet(Byte(2),1) = 1 then print " F6 on"; else print " F6 off"; endif if BitGet(Byte(2),2) = 1 then print " F7 on"; else print " F7 off"; endif if BitGet(Byte(2),3) = 1 then print " F8 on" else print " F8 off" endif Decoded = 1 endif if Byte(0) = $B0 then ' Switch request Address = ((Byte(2) & $0f) * 128) + Byte(1) + 1 print "Sw Req " + Address; if BitGet (Byte(2), 5) > 0 then print " thrown"; else print " closed"; endif if BitGet (Byte(2), 4) > 0 then print " on" else print " off" endif Decoded = 1 endif if Byte(0) = $B1 then ' turnout sensor report Address = ((Byte(2) & $0f) * 128) + Byte(1) + 1 if BitGet (Byte(2), 6) > 0 then print "Sw Rpt In " + Address; if BitGet (Byte(2), 5) > 0 then print " Sw"; else print " Aux"; endif if BitGet (Byte(2), 4) > 0 then print " Hi" else print " Low" endif else print "Sw Rpt Out " + Address; if BitGet (Byte(2), 4) > 0 then print " thrown on"; else print " thrown off"; endif if BitGet (Byte(2), 5) > 0 then print " closed on" else print " closed off" endif endif Decoded = 1 endif if Byte(0) = $B2 then ' general sensor report Address = ((Byte(2) & $0f) * 256) + (Byte(1) * 2) + 1 if BitGet (Byte(2), 5) > 0 then Address = Address + 1 endif print "Gen Sn " + Address; if BitGet (Byte(2), 4) > 0 then print " Hi" else print " Low" endif Decoded = 1 endif if Byte(0) = $B4 then ' long ack Select Integer Byte(1) Case $30 print "SW Req failed" Case $39 print "Invalid consist link" Case $3A print "Illegal Slot Move" Case $3D if Byte(2) = $7F then print "Switch Req accepted" else print "FIFO full, SW Req rejected" endif Case $3F print "Slot full" Case $7E print "IMM Limited master <" + Convert(Byte(2),"X") + ">" Case $7D if Byte(2) = $7F then print "IMM accepted" else print "IMM busy" endif Case $7F if Byte(2) = 0 then print "Prog busy, aborted, no reply" if Byte(2) = 1 then print "Prog accepted, reply at complete" if Byte(2) = $40 then print "Prog accepted, no reply" if Byte(2) = $7F then print "Prog not implelemted, no reply" CaseElse print "Long Ack OPC=" + Byte(1) + " ACK= " + Byte(2) endSelect Decoded = 1 endif if Byte(0) = $B5 then ' write status to slot print "Write Slot " + Byte(1) + " to"; LocoStatus(Byte(2)) Decoded = 1 endif if Byte(0) = $B6 then ' consist function set print "Con Func Slot " + Byte(1) + " to"; LocoDirF(Byte(2)) Decoded = 1 endif if Byte(0) = $B8 then ' consist un link print "Con UnLink Slot " + Byte(1) + " from Slot " + Byte(2) Decoded = 1 endif if Byte(0) = $B9 then ' consist link print "Con Link Slot " + Byte(1) + " to Slot " + Byte(2) Decoded = 1 endif if Byte(0) = $BA then if Byte(1) = 0 then print "Dispatch get to Slot " + Byte(2) endif if Byte(2) = 0 then print "Dispatch put from Slot " + Byte(1) endif if Byte(1) = Byte(2) then print "Slot " + Byte(1) + " set in-use" else print "Move Slot " + Byte(1) + " to Slot " + Byte(2) endif Decoded = 1 endif if Byte(0) = $BB then ' Request slot data print "Req Slot " + Byte(1) + " Status" Decoded = 1 endif if Byte(0) = $BC then ' Request switch data Address = ((Byte(2) & $0f) * 128) + Byte(1) print "Req Switch " + Address + " Status" Decoded = 1 endif if Byte(0) = $BD then ' Request switch with Ack Address = ((Byte(2) & $0f) * 128) + Byte(1) print "Req Switch " + Address; if BitGet (Byte(2), 5) > 0 then print " thrown"; else print " closed"; endif if BitGet (Byte(2), 4) > 0 then print " on"; else print " off"; endif print " w/ Ack" Decoded = 1 endif if Byte(0) = $BF then ' Request slot for address Address = Byte(1) * 128 + Byte(2) print "Req slot for Add " + Address Decoded = 1 endif if Byte(0) = $E7 then ' read slot data Select Integer Byte(2) Case $7B ' Clock data print "R "; gosub ClockData Case $7C ' Programming Address = Byte(5) * 128 + Byte(6) CV = Byte(9) Data = Byte(10) if BitGet(Byte(8), 0) = 1 then BitSet(CV, 7, 1) if BitGet(Byte(8), 4) = 1 then BitSet(CV, 8, 1) if BitGet(Byte(8), 5) = 1 then BitSet(CV, 9, 1) if BitGet(Byte(8), 1) = 1 then BitSet(Data, 7, 1) print "Prog reply"; if Byte(4) > 0 then if BitGet(Byte(4),0) = 1 then print " No Dec"; if BitGet(Byte(4),1) = 1 then print " No Ack"; if BitGet(Byte(4),2) = 1 then print " No Read"; if BitGet(Byte(4),3) = 1 then print " Aborted"; else print " P"; if BitGet(Byte(3),2) = 1 then print "o "; else if BitGet(Byte(3),4) = 1 then print "h "; else if BitGet(Byte(3),3) = 1 then print "d "; else print "g "; endif endif endif if BitGet(Byte(3),6) = 1 then print "W " + Data + " to CV" + CV; else print "R " + Data + " from CV" +CV; endif if BitGet(Byte(3),2) = 1 then print " on A" + Address else print " " endif endif CaseElse ' slot data print "R "; GoSub SlotData EndSelect Decoded = 1 endif if Byte(0) = $ED then ' immeadiate DCC command if (Byte(4) & $01) > 0 then Byte(5) = BitSet(Byte(5), 7, 1) if (Byte(4) & $02) > 0 then Byte(6) = BitSet(Byte(6), 7, 1) if (Byte(4) & $04) > 0 then Byte(7) = BitSet(Byte(7), 7, 1) if (Byte(4) & $08) > 0 then Byte(8) = BitSet(Byte(8), 7, 1) if (Byte(4) & $10) > 0 then Byte(9) = BitSet(Byte(9), 7, 1) Count = Byte(3) & $07 Bytes = Byte(3) \ 16 print "IMM C=" + Count + "B=" + Bytes + " P="; for i = 1 to Bytes print " " + Convert(Byte(i+4),"X"); next print "" if Bytes = 4 then ' extra DCC decode for F9-F28 if Byte(7) = $DE then Address = ((Byte(5) - $C0) * 256) + Byte(6) print " -> Add " + Address; if BitGet(Byte(8),0) = 1 then print " F13 on"; else print " F13 off"; endif if BitGet(Byte(8),1) = 1 then print " F14 on"; else print " F14 off"; endif if BitGet(Byte(8),2) = 1 then print " F15 on"; else print " F15 off"; endif if BitGet(Byte(8),3) = 1 then print " F16 on" else print " F16 off" endif if BitGet(Byte(8),4) = 1 then print " --> F17 on"; else print " --> F17 off"; endif if BitGet(Byte(8),5) = 1 then print " F18 on"; else print " F18 off"; endif if BitGet(Byte(8),6) = 1 then print " F19 on"; else print " F19 off"; endif if BitGet(Byte(8),7) = 1 then print " F20 on" else print " F20 off" endif endif if Byte(7) = $DF then Address = ((Byte(5) - $C0) * 256) + Byte(6) print " -> Add " + Address; if BitGet(Byte(8),0) = 1 then print " F21 on"; else print " F21 off"; endif if BitGet(Byte(8),1) = 1 then print " F22 on"; else print " F22 off"; endif if BitGet(Byte(8),2) = 1 then print " F23 on"; else print " F23 off"; endif if BitGet(Byte(8),3) = 1 then print " F24 on" else print " F24 off" endif if BitGet(Byte(8),4) = 1 then print " --> F25 on"; else print " --> F25 off"; endif if BitGet(Byte(8),5) = 1 then print " F26 on"; else print " F26 off"; endif if BitGet(Byte(8),6) = 1 then print " F27 on"; else print " F27 off"; endif if BitGet(Byte(8),7) = 1 then print " F28 on" else print " F28 off" endif endif endif if Bytes = 3 then if Byte(5) > 127 then if (Byte(7) & $f0) = $A0 then Address = ((Byte(5) - $C0) * 256) + Byte(6) print " -> Add " + Address; if BitGet(Byte(7),0) = 1 then print " F9 on"; else print " F9 off"; endif if BitGet(Byte(7),1) = 1 then print " F10 on"; else print " F10 off"; endif if BitGet(Byte(7),2) = 1 then print " F11 on"; else print " F11 off"; endif if BitGet(Byte(7),3) = 1 then print " F12 on" else print " F12 off" endif endif else if Byte(6) = $DE then print " -> Add " + Byte(5); if BitGet(Byte(7),0) = 1 then print " F13 on"; else print " F13 off"; endif if BitGet(Byte(7),1) = 1 then print " F14 on"; else print " F14 off"; endif if BitGet(Byte(7),2) = 1 then print " F15 on"; else print " F15 off"; endif if BitGet(Byte(7),3) = 1 then print " F16 on" else print " F16 off" endif if BitGet(Byte(7),4) = 1 then print " --> F17 on"; else print " --> F17 off"; endif if BitGet(Byte(7),5) = 1 then print " F18 on"; else print " F18 off"; endif if BitGet(Byte(7),6) = 1 then print " F19 on"; else print " F19 off"; endif if BitGet(Byte(7),7) = 1 then print " F20 on" else print " F20 off" endif endif if Byte(6) = $DF then print " -> Add " + Byte(5); if BitGet(Byte(7),0) = 1 then print " F21 on"; else print " F21 off"; endif if BitGet(Byte(7),1) = 1 then print " F22 on"; else print " F22 off"; endif if BitGet(Byte(7),2) = 1 then print " F23 on"; else print " F23 off"; endif if BitGet(Byte(7),3) = 1 then print " F24 on" else print " F24 off" endif if BitGet(Byte(7),4) = 1 then print " --> F25 on"; else print " -->F25 off"; endif if BitGet(Byte(7),5) = 1 then print " F26 on"; else print " F26 off"; endif if BitGet(Byte(7),6) = 1 then print " F27 on"; else print " F27 off"; endif if BitGet(Byte(7),7) = 1 then print " F28 on" else print " F28 off" endif endif endif endif if Bytes = 2 then if (Byte(6) & $f0) = $A0 then print " -> Add " + Byte(5); if BitGet(Byte(6),0) = 1 then print " F9"; else print " F-"; endif if BitGet(Byte(6),1) = 1 then print " 10"; else print " -"; endif if BitGet(Byte(6),2) = 1 then print " 11"; else print "-"; endif if BitGet(Byte(6),3) = 1 then print " 12" else print "-" endif endif endif Decoded = 1 endif if Byte(0) = $EF then ' Slot Write Select Integer Byte(2) Case $7B ' Clock data print "W "; gosub ClockData Case $7C ' Programming Address = Byte(5) * 128 + Byte(6) CV = Byte(9) Data = Byte(10) if BitGet(Byte(8), 0) = 1 then BitSet(CV, 7, 1) if BitGet(Byte(8), 4) = 1 then BitSet(CV, 8, 1) if BitGet(Byte(8), 5) = 1 then BitSet(CV, 9, 1) if BitGet(Byte(8), 1) = 1 then BitSet(Data, 7, 1) print "P"; if BitGet(Byte(3),2) = 1 then print "o "; else if BitGet(Byte(3),4) = 1 then print "h "; else if BitGet(Byte(3),3) = 1 then print "d "; else print "g "; endif endif endif if BitGet(Byte(3),6) = 1 then print "W" + Data + " to CV" + CV; else print "R from CV" +CV; endif if BitGet(Byte(3),2) = 1 then print " on A" + Address else print " " endif CaseElse 'Write Slot Data print "W "; GoSub SlotData EndSelect Decoded = 1 endif if Decoded = 0 then print "*** Unknown " + Line endif if Raw = 1 then print " " exit() SlotData: Address = Byte(9) * 128 + Byte(4) print "St" + Byte(2) + " Ad" + Address + " Sp" + Byte(5); LocoDirF(Byte(6)) LocoSnd(Byte(10)) LocoStatus(Byte(3)) return ClockData: Hours = ((256 - Byte(8))& $7f) // 24 Hours = (24 - Hours) // 24 Minutes = ((255 - Byte(6)) & $7f) // 60 Minutes = (60 - Minutes) // 60 FracMins = $3FFF - ( Byte(4) + ( Byte(5) * 128 ) ) if BitGet(Byte(10),6) = 1 then print "Clock valid Rate="+Byte(3)+":1 Day "+Byte(9)+" "+Hours+":"+Minutes+"."+FracMins+"ID="+Byte(11)+","+Byte(12) else print "Clock invalid Rate="+Byte(3)+":1 Day "+Byte(9)+" "+Hours+":"+Minutes+"."+FracMins+"ID="+Byte(11)+","+Byte(12) endif return endfunc '------------------------------------------------------------------------------- func LocoSnd(Snd as integer) if BitGet(Snd,0) = 1 then print "5"; else print "-"; endif if BitGet(Snd,1) = 1 then print "6"; else print "-"; endif if BitGet(Snd,2) = 1 then print "7"; else print "-"; endif if BitGet(Snd,3) = 1 then print "8"; else print "-"; endif endfunc '------------------------------------------------------------------------------- func LocoDirF(DirF as integer) if BitGet(DirF,5) = 1 then print " For F"; else print " Rev F"; endif if BitGet(DirF,4) = 1 then print "O"; else print "-"; endif if BitGet(DirF,0) = 1 then print "1"; else print "-"; endif if BitGet(DirF,1) = 1 then print "2"; else print "-"; endif if BitGet(DirF,2) = 1 then print "3"; else print "-"; endif if BitGet(DirF,3) = 1 then print "4"; else print "-"; endif endfunc '------------------------------------------------------------------------------- func LocoStatus(Stat as integer) if (Stat & $07) = 0 then print " 28SS"; endif if (Stat & $07) = 1 then print " Tri"; endif if (Stat & $07) = 2 then print " 14SS"; endif if (Stat & $07) = 3 then print " 128SS"; endif if (Stat & $07) = 4 then print " 28Adv"; endif if (Stat & $07) = 7 then print " 128Adv"; endif if (Stat & $48) = 0 then print " UnCon"; endif if (Stat & $48) = 8 then print " Sub"; endif if (Stat & $48) = $40 then print " Top"; endif if (Stat & $48) = $48 then print " Mid"; endif if (Stat & $30) = $00 then print " Free" endif if (Stat & $30) = $10 then print " Common" endif if (Stat & $30) = $20 then print " Idle" endif if (Stat & $30) = $30 then print " In Use" endif endfunc '------------------------------------------------------------------------------- func DecodeFile() dim Line as string dim FileName as string FileName = FormTextBox(Text_FileName) if FileOpen(FileChannel,FileName,Open) = 1 then print "Opened "+FileName else print FileName + " not opened" exit() endif LoopFile: if FileEOF(FileChannel) = 0 then Line = FileReadLine(FileChannel) Decode (Line) else FileClose(FileChannel) exit() endif goto LoopFile endfunc '------------------------------------------------------------------------------- func HexToDec(Hex as string) as integer dim LeftChar as string dim RightChar as string LeftChar = Left(Hex, 1) RightChar = Right(Hex, 1) exit(DecDigit(LeftChar) * 16 + DecDigit(RightChar)) endfunc '------------------------------------------------------------------------------- func DecDigit(Digit as string) as integer StrIf Digit = "0" then exit (0) StrIf Digit = "1" then exit (1) StrIf Digit = "2" then exit (2) StrIf Digit = "3" then exit (3) StrIf Digit = "4" then exit (4) StrIf Digit = "5" then exit (5) StrIf Digit = "6" then exit (6) StrIf Digit = "7" then exit (7) StrIf Digit = "8" then exit (8) StrIf Digit = "9" then exit (9) StrIf Digit = "A" then exit (10) StrIf Digit = "B" then exit (11) StrIf Digit = "C" then exit (12) StrIf Digit = "D" then exit (13) StrIf Digit = "E" then exit (14) StrIf Digit = "F" then exit (15) endfunc '------------------------------------------------------------------------------- func Main_DisplayForm() FormRes(240,268) ' FormRes(500,500) Console(5) ' mini console FormNew() FormBGColor(228,228,228) FormCLS() '--- Buttons --- gconst Button_Quit 0 gconst Button_Start 1 gconst Button_Stop 2 gconst Button_Raw 3 gconst Button_File 4 gconst Button_Save 5 gconst Button_FullSrn 6 '--- Labels --- gconst Label_Heading 0 gconst Label_IP 1 gconst Label_Port 2 gconst Label_Raw 3 '--- TextBoxes --- gconst Text_IP 0 gconst Text_Port 2 gconst Text_FileName 3 FormTextColor(0,0,0) FormFont("-",10,1) FormSettings(AlignCenter) FormLabel(Label_Heading,5,1,228,20,"Loconet Monitor") FormFont("-",9,0) FormSettings(AlignRight) FormLabel(Label_IP, 80,25,50,20,"IP:") FormLabel(Label_Port,80,45,50,20,"Port:") FormPen(255,255,255) FormRectangle(140,135,7,20) FormBrush(128,128,0) FormFillRectangle(141,136,5,18) FormSettings(Alignleft) FormBGColor(255,255,255) FormFont("-",9,0) FormTextBox(Text_IP ,135,25,100,20,IP) FormTextBox(Text_Port,135,45,100,20,Port) FormSettings(Alignleft) FormTextBox(Text_FileName,75,100,150,20,".\loconet.txt") FormBGColor(211,211,211) FormFont("-",9,1) FormButton(Button_Quit, 10, 135, 60, 20, "Quit") FormButton(Button_Start, 10, 25, 60, 20, "Start") FormButton(Button_Stop, 10, 45, 60, 20, "Stop") FormButton(Button_Raw, 80, 135, 60, 20, "Raw") FormButton(Button_File, 10, 100, 60, 20, "File") FormButton(Button_Save, 135, 64, 70, 20, "Save") FormButton(Button_FullSrn, 10, 70, 100, 20, "Full Console") FormSettings(Alignleft) FormBGColor(228,228,228) endfunc