Skip to content

Commit c7c75e4

Browse files
committed
periodically verify shared memory data version, auto restart memory mapping if data version stopped updating
1 parent 01df594 commit c7c75e4

2 files changed

Lines changed: 102 additions & 45 deletions

File tree

rF2data.py

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from enum import Enum
88
import ctypes
99
import mmap
10+
import copy
1011

1112
class rFactor2Constants:
1213
MAX_MAPPED_VEHICLES = 128
@@ -692,26 +693,78 @@ class SubscribedBuffer(Enum):
692693

693694
class SimInfo:
694695
def __init__(self, input_pid):
696+
self._input_pid = input_pid
695697

698+
self._rf2_tele = None # map shared memory
699+
self._rf2_scor = None
700+
self._rf2_ext = None
701+
self._rf2_ffb = None
702+
703+
self.Rf2Tele = None # raw data
704+
self.Rf2Scor = None
705+
self.Rf2Ext = None
706+
self.Rf2Ffb = None
707+
708+
self.DefTele = None # default copy of raw data
709+
self.DefScor = None
710+
self.DefExt = None
711+
self.DefFfb = None
712+
713+
self.LastTele = None # synced copy of raw data
714+
self.LastScor = None
715+
self.LastExt = None
716+
self.LastFfb = None
717+
718+
self.start_mmap()
719+
self.set_default_mmap()
720+
721+
def start_mmap(self):
722+
""" Start memory mapping """
723+
self._rf2_tele = mmap.mmap(0, ctypes.sizeof(rF2Telemetry), f"$rFactor2SMMP_Telemetry${self._input_pid}")
724+
self._rf2_scor = mmap.mmap(0, ctypes.sizeof(rF2Scoring), f"$rFactor2SMMP_Scoring${self._input_pid}")
725+
self._rf2_ext = mmap.mmap(0, ctypes.sizeof(rF2Extended), f"$rFactor2SMMP_Extended${self._input_pid}")
726+
self._rf2_ffb = mmap.mmap(0, ctypes.sizeof(rF2ForceFeedback), "$rFactor2SMMP_ForceFeedback$")
696727

697-
self._rf2_tele = mmap.mmap(0, ctypes.sizeof(rF2Telemetry), f"$rFactor2SMMP_Telemetry${input_pid}")
698728
self.Rf2Tele = rF2Telemetry.from_buffer(self._rf2_tele)
699-
self._rf2_scor = mmap.mmap(0, ctypes.sizeof(rF2Scoring), f"$rFactor2SMMP_Scoring${input_pid}")
700729
self.Rf2Scor = rF2Scoring.from_buffer(self._rf2_scor)
701-
self._rf2_ext = mmap.mmap(0, ctypes.sizeof(rF2Extended), f"$rFactor2SMMP_Extended${input_pid}")
702730
self.Rf2Ext = rF2Extended.from_buffer(self._rf2_ext)
703-
self._rf2_ffb = mmap.mmap(0, ctypes.sizeof(rF2ForceFeedback), "$rFactor2SMMP_ForceFeedback$")
704731
self.Rf2Ffb = rF2ForceFeedback.from_buffer(self._rf2_ffb)
705732

733+
self.DefTele = copy.deepcopy(self.Rf2Tele)
734+
self.DefScor = copy.deepcopy(self.Rf2Scor)
735+
self.DefExt = copy.deepcopy(self.Rf2Ext)
736+
self.DefFfb = copy.deepcopy(self.Rf2Ffb)
737+
738+
def set_default_mmap(self):
739+
""" Set default memory mapping data """
740+
self.LastTele = copy.deepcopy(self.DefTele)
741+
self.LastScor = copy.deepcopy(self.DefScor)
742+
self.LastExt = copy.deepcopy(self.DefExt)
743+
self.LastFfb = copy.deepcopy(self.DefFfb)
744+
745+
def reset_mmap(self):
746+
""" Reset memory mapping """
747+
self.close() # close mmap first
748+
self.start_mmap()
749+
706750
def close(self):
707-
# This didn't help with the errors
708-
try:
709-
self._rf2_tele.close()
710-
self._rf2_scor.close()
711-
self._rf2_ext.close()
712-
self._rf2_ffb.close()
713-
except BufferError: # "cannot close exported pointers exist"
714-
pass
751+
""" Close memory mapping """
752+
# This didn't help with the errors
753+
try:
754+
# Unassign those objects first
755+
self.Rf2Tele = None
756+
self.Rf2Scor = None
757+
self.Rf2Ext = None
758+
self.Rf2Ffb = None
759+
# Close shared memory mapping
760+
self._rf2_tele.close()
761+
self._rf2_scor.close()
762+
self._rf2_ext.close()
763+
self._rf2_ffb.close()
764+
print("sharedmemory mapping closed")
765+
except BufferError: # "cannot close exported pointers exist"
766+
print("BufferError")
767+
pass
715768

716769
def __del__(self):
717770
self.close()

sharedMemoryAPI.py

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,12 @@ class SimInfoAPI(rF2data.SimInfo):
2828
rf2_pid_counter = 0 # Counter to check if running
2929
rf2_running = False
3030

31-
def __init__(self, input_pid):
31+
def __init__(self, input_pid=""):
3232
rF2data.SimInfo.__init__(self, input_pid)
3333
self.versionCheckMsg = self.versionCheck()
3434
self.__find_rf2_pid()
35+
3536
self.players_index = 99
36-
self.players_status = 0
37-
self.LastTele = copy.deepcopy(self.Rf2Tele)
38-
self.LastScor = copy.deepcopy(self.Rf2Scor)
3937
self.data_updating = False
4038
print("sharedmemory mapping started")
4139

@@ -137,11 +135,18 @@ def dataVerified(input_data):
137135

138136
def __infoUpdate(self):
139137
""" Update synced player data """
140-
players_mid = 0
138+
players_mid = 0 # player mID
139+
last_version_update = 0 # store last data version update
140+
re_version_update = 0 # store restarted data version update
141+
mmap_restarted = True # whether has restarted memory mapping
142+
check_counter = 0 # counter for data version update check
143+
restore_counter = 0 # counter for restoring mmap data to default
141144

142145
while self.data_updating:
143146
data_scor = copy.deepcopy(self.Rf2Scor) # use deepcopy to avoid data interruption
144147
data_tele = copy.deepcopy(self.Rf2Tele)
148+
self.LastExt = copy.deepcopy(self.Rf2Ext)
149+
self.LastFfb = copy.deepcopy(self.Rf2Ffb)
145150

146151
# Only update if data verified and player index found
147152
if self.dataVerified(data_scor) and self.__playerVerified(data_scor):
@@ -151,7 +156,31 @@ def __infoUpdate(self):
151156
# Only update if data verified and player mID matches
152157
if self.dataVerified(data_tele) and data_tele.mVehicles[self.players_index].mID == players_mid:
153158
self.LastTele = copy.deepcopy(data_tele) # use deepcopy to update synced telemetry data
154-
self.players_status = self.LastTele.mVehicles[self.players_index].mIgnitionStarter # update player status
159+
160+
# Start checking data version update status
161+
check_counter += 1
162+
163+
if check_counter > 70: # active after around 1 seconds
164+
if not mmap_restarted and last_version_update > 0 and last_version_update == self.LastScor.mVersionUpdateEnd:
165+
self.reset_mmap()
166+
mmap_restarted = True
167+
re_version_update = self.LastScor.mVersionUpdateEnd
168+
print(f"sharedmemory mapping restarted - version:{last_version_update}")
169+
last_version_update = self.LastScor.mVersionUpdateEnd
170+
check_counter = 0 # reset counter
171+
172+
if mmap_restarted:
173+
if re_version_update != self.LastScor.mVersionUpdateEnd:
174+
mmap_restarted = False
175+
restore_counter = 0 # reset counter
176+
elif restore_counter < 71:
177+
restore_counter += 1
178+
179+
if restore_counter == 70: # active after around 1 seconds
180+
self.set_default_mmap()
181+
print("sharedmemory mapping data reset to default")
182+
183+
#print(f"c1:{check_counter:03.0f} c2:{restore_counter:03.0f} now:{self.LastScor.mVersionUpdateEnd:07.0f} last:{last_version_update:07.0f} re:{re_version_update:07.0f} {mmap_restarted}", end="\r")
155184

156185
time.sleep(0.01)
157186
else:
@@ -245,9 +274,7 @@ def isAiDriving(self):
245274
# didn't work self.Rf2Ext.mPhysics.mAIControl
246275

247276
def driverName(self):
248-
"""
249-
Get the player's name
250-
"""
277+
""" Get the player's name """
251278
return Cbytestring2Python(
252279
self.Rf2Scor.mVehicles[self.__playersDriverNum()].mDriverName)
253280

@@ -260,33 +287,10 @@ def playersVehicleScoring(self):
260287
return self.Rf2Scor.mVehicles[self.__playersDriverNum()]
261288

262289
def vehicleName(self):
263-
"""
264-
Get the vehicle's name
265-
"""
290+
""" Get the vehicle's name """
266291
return Cbytestring2Python(
267292
self.Rf2Scor.mVehicles[self.__playersDriverNum()].mVehicleName)
268293

269-
def closeSimInfo(self):
270-
# This didn't help with the errors
271-
try:
272-
# Unassign those objects first
273-
self.Rf2Tele = None
274-
self.Rf2Scor = None
275-
self.Rf2Ext = None
276-
self.Rf2Ffb = None
277-
# Close shared memory mapping
278-
self._rf2_tele.close()
279-
self._rf2_scor.close()
280-
self._rf2_ext.close()
281-
self._rf2_ffb.close()
282-
print("sharedmemory mapping closed")
283-
except BufferError: # "cannot close exported pointers exist"
284-
print("BufferError")
285-
pass
286-
287-
def __del__(self):
288-
self.close()
289-
290294

291295
def Cbytestring2Python(bytestring):
292296
"""

0 commit comments

Comments
 (0)