import socket
import sys
import struct
import math
import datetime
# pip3 install salsa20
from salsa20 import Salsa20_xor
#https://github.com/Nenkai/PDTools/blob/master/SimulatorInterface/SimulatorInterface.cs
SendDelaySeconds = 10
ReceivePort = 33740
SendPort = 33739
port = ReceivePort
if len(sys.argv) == 2:
# Get "IP address of Server" and also the "port number" from
ip = sys.argv[1]
else:
print("Run like : python3 pd-lapcounter-demo.py <playstation-ip>")
exit(1)
# Create a UDP socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Bind the socket to the port
server_address = ('0.0.0.0', port)
s.bind(server_address)
s.settimeout(10)
#https://github.com/Nenkai/PDTools/blob/master/PDTools.Crypto/SimulationInterface/SimulatorInterfaceCryptorGT7.cs
def salsa20_dec(dat):
KEY = b'Simulator Interface Packet GT7 ver 0.0'
oiv = dat[0x40:0x44]
iv1 = int.from_bytes(oiv, byteorder='little') # Seed IV is always located there
iv2 = iv1 ^ 0xDEADBEAF #// Notice DEADBEAF, not DEADBEEF
IV = bytearray()
IV.extend(iv2.to_bytes(4, 'little'))
IV.extend(iv1.to_bytes(4, 'little'))
ddata = Salsa20_xor(dat, bytes(IV), KEY[0:32])
#check magic number
magic = int.from_bytes(ddata[0:4], byteorder='little')
if magic != 0x47375330:
return bytearray(b'')
return ddata
def send_hb(s):
#send HB
send_data = 'A'
s.sendto(send_data.encode('utf-8'), (ip, SendPort))
print('send heartbeat')
class LapCounter:
def __init__(self):
self.lap = -1
self.paused = -1
self.tick = 0
self.pstart_tick = 0
self.lstart_tick = 0
self.lstart_ms = 0
self.paused_ticks = 0
self.last_lap_ms = 0
self.special_packet_time = 0
def update(self,lap,paused,tick,last_lap_ms):
if lap == 0: # we have not started a lap or have reset
self.special_packet_time = 0
if lap != self.lap: # we have entered a new lap
if self.lap != 0:
normal_laptime = self.lapticks()*1000.0/60.0
self.special_packet_time += last_lap_ms - self.lapticks()*1000.0/60.0
self.lstart_tick = self.tick
self.paused_ticks = 0
if paused != self.paused: # paused has changed
if paused: # we have switched to paused
self.pstart_tick = self.tick
else: # we have switched to not paused
self.paused_ticks += tick - self.pstart_tick
self.paused = paused
self.lap = lap
self.tick = tick
self.last_lap_ms = last_lap_ms
def pausedticks(self):
if not self.paused:
return self.paused_ticks
else:
return self.paused_ticks + (self.tick - self.pstart_tick)
def lapticks(self):
if self.lap == 0:
return 0
else:
return self.tick - self.lstart_tick - self.pausedticks()
def laptime(self):
laptime = (self.lapticks() * 1./60.) - (self.special_packet_time/1000.)
return round(laptime,3)
send_hb(s)
print("Ctrl+C to exit the program")
pknt = 0
lapcounter = LapCounter()
while True:
try:
data, address = s.recvfrom(4096)
pknt = pknt + 1
print("received: %d bytes" % len(data))
ddata = salsa20_dec(data)
if len(ddata) > 0:
tick = struct.unpack_from('i',ddata,0x70)
current_lap,laps_remaining = struct.unpack_from('hh',ddata,0x74)
best_lap_ms,last_lap_ms = struct.unpack_from('ii',ddata,0x78)
rpm_min,rpm_max,v_max,flags = struct.unpack_from('hhhh',ddata,0x88)
paused = flags&2 # second bit in flags is paused
lapcounter.update(current_lap,paused,tick[0],last_lap_ms)
print ("lapcounter.laptime:",lapcounter.laptime())
if pknt > 900:
send_hb(s)
pknt = 0
except Exception as e:
print(e)
send_hb(s)
pknt = 0
pass