Saving and loading state
In many cases, it may be desirable to save the state a device or axis is currently in. Perhaps you're about to begin playing with settings and want to revert to a known-good state if the changes don't work out. Perhaps you have a device used for a few different tasks and want a way to quickly load a suite of stream buffers or triggers for the different contents. Perhaps you have a controller with many peripherals and after configuring one, you'd like to copy that configuration to the other peripherals without manually tweaking dozens of settings. ZML save states can help.
What is Saved
When you save the state of an axis, the following information is saved:
- ID and serial number
- All settings
- Local storage
- Servo Tunings
- Stored Positions
For devices and controllers, all the above is saved is stored, as well as:
- Triggers
- Stream Buffers
- PVT Buffers
- The complete state of all connected peripherals (if this device is a controller)
Where can a saved state be loaded
In general, you can only load a saved state to a device or axis that is identical to the one that the save was created from and has firmware at least as recent. So a save file created from an LRQ running firmware 7.22 could be loaded on to an LRQ running firmware 7.22 or 7.25, but not an LRQ running 7.21 or any RSM no matter what the firmware.
If you are trying to apply a state to a controller, it will further expect that all of the peripherals are as they were when the state
was created, and the saved state of its peripherals will also be applied. Although note that if you run
set_state
with the deviceOnly
flag set true, the peripherals will be ignored and only controller-level state will be applied.
Save Files
Creating a save
To create a save, call
get_state
. This will return a string representing the current state of the device or axis. From there, you can save
that string to a file:
def save_state(device: Device):
state = device.get_state()
with open('save.json', 'w', encoding='utf-8') as save_file:
save_file.write(state)
Loading a Save
To use that save file, read its content into your program and then use that set the device's state:
def load_state(device: Device):
with open('save.json', 'r', encoding='utf-8') as save_file:
state = save_file.read()
device.set_state(state)
Reverting to a previous state
You can use these functions to roll back changes to a device. In this case I'm just undoing a single setting change, but this can be used to undo any changes made to your device.
device = connection.get_device(1)
device.identify()
# Save the current state of the device
MM_S = Units.VELOCITY_MILLIMETRES_PER_SECOND
initial_maxspeed = device.settings.get('maxspeed', MM_S)
save_state(device)
# Make some changes
device.settings.set('maxspeed', 1.5, MM_S)
assert device.settings.get('maxspeed', MM_S) != initial_maxspeed
# After loading, the device is back to its initial state
load_state(device)
assert device.settings.get('maxspeed', MM_S) == initial_maxspeed
Peripheral State Propagation
Let's say you've got an X-MCC4 with 4 peripherals attached. All of them are the same, and you want to make multiple changes to each of them (perhaps a complex Advanced Hardware Setup). You could go through and apply these changes to each peripheral, one after the next, but with a bit of code, you can save yourself sometime. Let's say you've made the changes you want to make to the first peripheral, then all you'd need to do is run the following script:
mcc4 = connection.get_device(1)
mcc4.identify()
# Get the state from the first peripheral
peripheral_state = mcc4.get_axis(1).get_state()
# Set the state to all of the other peripherals
mcc4.get_axis(2).set_state(peripheral_state)
mcc4.get_axis(3).set_state(peripheral_state)
mcc4.get_axis(4).set_state(peripheral_state)
And all your peripherals would have the same state loaded up!