Open tony-gutierrez opened 9 months ago
Just noticed line 153. I wonder if there is any harm in not waiting for encoding to be false. Or if there could be a way to specify that we don't care.
It could get initial state, and then set the _busy and _encoding flags to the appropriate initial values. However I have noticed that _encoding does not get updated when starting the shutter, and appears to only be updated if the user happens to call is_ready().
I actually think this is behaving as expected. The Wireless / Wired GoPro classes track the encoding
and ready
statuses so that they know when to allow communication.
If the camera is encoding, it will not accept commands (besides Set Shutter Off).
One option is to always set shutter off when opening the WiredGoPro. However I don't think that is desired behavior, at least not by default. It seems to me that if you started recorded on the camera UI, it is up to you to stop recording on the camera UI. However, if you think otherwise I could entertain the idea of a "force_init" argument to WiredGoPro that would send "Set Shutter Off"
We have a commercial use where a robot drives around with 8 cams on it. We have to use multiprocessing in python, which means each process (8 total) briefly talks to one camera to do an action (configure, start and stop). The processes end after each action. I am working around it for now with the stop shutter, but if our main host program crashes or something like that, we currently cannot stop recording via the SDK.
An option to force stop on open would help, but I would prefer an option to bypass the wait for state check. That way we could do more controlled things like check the recorded duration, stop, and then DL media
The wiredGoPro is not currently accurately tracking the encoding status, so I don't think it would be a breaking change to have a wiredGoPro created, bypass the check, and it think it is not recording. It could even be an enhancement so that encoding:true is accurately set on reopen.
For others, I solved this for now by forcing an http call to the camera upon detection, before instantiating a WiredGoPro instance. You will need to create the baseUrl using the ip of the camera. I have the IP from my own _find_mult_serial_via_mdns
function that detects multiple cameras, but you can also craft it from the camera serial number.
async def forceStopShutter(baseUrl):
async with aiohttp.ClientSession() as session:
async with session.get(baseUrl + 'gopro/camera/shutter/stop') as resp:
return resp.status == 200
I plan at some point to do a major redesign to both:
Perhaps part of this will be to allow configurable strategies for at least initialization as is discussed here.
I came across the same problem and my solution is to start a second method on the same object which stops recording if the camera is busy.
async def _open(self):
async def stop_shutter():
while True:
try:
self._logger.debug(f"Try to stop recording on open() for {self.__cam.identifier}")
break
except open_gopro.exceptions.GoProNotOpened:
await asyncio.sleep(1)
state = (await self.__cam.http_command.get_camera_state()).data
if state.get(constants.StatusId.ENCODING) or state.get(constants.StatusId.SYSTEM_BUSY):
await self.__cam.http_command.set_shutter(shutter=Params.Toggle.DISABLE)
await asyncio.gather(self.__cam.open(), stop_shutter())
The method can simply be called with await self._open()
instead of the original call await self.__cam.open()
.
I just rewrote in node, python was sluggish controlling multiple cameras, and the SDK is missing many of the available settings.
On Sat, May 4, 2024, 12:59 PM Philipp Strobel @.***> wrote:
I came across the same problem and my solution is to start a second method on the same object which stops recording if the camera is busy.
async def _open(self): async def stop_shutter(): while True: try: self._logger.debug(f"Try to stop recording on open() for {self.__cam.identifier}") break except open_gopro.exceptions.GoProNotOpened: await asyncio.sleep(1)
state = (await self.__cam.http_command.get_camera_state()).data if state.get(constants.StatusId.ENCODING) or state.get(constants.StatusId.SYSTEM_BUSY): await self.__cam.http_command.set_shutter(shutter=Params.Toggle.DISABLE) await asyncio.gather(self.__cam.open(), stop_shutter())
The method can simply be called with await self._open() instead of the original call await self.__cam.open().
— Reply to this email directly, view it on GitHub https://github.com/gopro/OpenGoPro/issues/405#issuecomment-2094301932, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADVCNM22FE5QGYQHZUJYWYTZAUHX5AVCNFSM6AAAAAA5CN2PWCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAOJUGMYDCOJTGI . You are receiving this because you authored the thread.Message ID: @.***>
Component What is the bug in?
Describe the bug If the camera is recording video, and you initiate a wiredGoPro object, and try to stop shutter, it will get stuck in repeatedly calling get state. It seems to be waiting for the camera to not be recording before it will allow the sending of the stop command.
If you call stop shutter with a WiredGoPro that has already been initiated and is past the get state step, it will stop the shutter correctly.
To Reproduce Steps to reproduce the behavior:
Expected behavior The stop shutter command is sent regardless of existing state.
Hardware
Additional context When using multiprocessing in python, it is often necessary for sub-processes to initiate a new wiredGoPro object as they cannot be passed among processes. With this but, a sub process is unable to kill the shutter that was started in another process.