kroo / wyzecam

Python package for streaming video from wyze cameras over the local network
https://kroo.github.io/wyzecam/
MIT License
170 stars 15 forks source link

Native Windows support #71

Open wildiness opened 3 years ago

wildiness commented 3 years ago

šŸš€ Feature Request

Add native Windows support. (without using WSL and Xming.)

The library can support windows natively if the DLL's are specified in the code instead of using a merged .so/.dylib file. Windows does not support merging DLL's.

šŸ”ˆ Motivation

Selfishly, I want to be able to view the camera stream using the efficient cv2.imshow().

I have not tried running it via WSL but I assume running it natively is faster.

šŸ›° Alternatives

Running it via WSL and Xming like proposed in the install instructions.

šŸ“Ž Additional context

I got it to run on Windows by changing the code to specify if tutk_platform_lib needed AVAPIs or IOTCAPIs. Now, I can't make a PR because it no longer supports Linux or MacOS. I don't know enough about g++ etc. to see why a merged library file is needed instead of just importing the two separate files. If Linux and MacOS can handle 2 separate files it could be cleaned up and merged, and support all 3 platforms.

I attach 2 patch files with the changes I made to get it to work. It's not a proper Git patch but it shows that the changes needed for Windows functionality are quite few.

wyzecam_on_windows

wyzecam/iotc.py:

62c62,63
<         tutk_platform_lib: Optional[Union[str, CDLL]] = None,
---
>         tutk_platform_lib_iotc: Optional[Union[str, CDLL]] = None,
>         tutk_platform_lib_av: Optional[Union[str, CDLL]] = None,
78,82c79,89
<         if tutk_platform_lib is None:
<             tutk_platform_lib = tutk.load_library()
<         if isinstance(tutk_platform_lib, str):
<             path = pathlib.Path(tutk_platform_lib)
<             tutk_platform_lib = tutk.load_library(str(path.absolute()))
---
>         if tutk_platform_lib_av is None:
>             tutk_platform_lib_av = tutk.load_library("C:\\Users\\[Redacted]\\PycharmProjects\\wyzestream\\tutk_lib\\Lib\\Windows\\x64\\AVAPIs.dll")
>         if isinstance(tutk_platform_lib_av, str):
>             path = pathlib.Path(tutk_platform_lib_av)
>             tutk_platform_lib_av = tutk.load_library(str(path.absolute()))
>             
>         if tutk_platform_lib_iotc is None:
>             tutk_platform_lib_iotc = tutk.load_library("C:\\Users\\[Redacted]\\PycharmProjects\\wyzestream\\tutk_lib\\Lib\\Windows\\x64\\IOTCAPIs.dll")
>         if isinstance(tutk_platform_lib_iotc, str):
>             path = pathlib.Path(tutk_platform_lib_iotc)
>             tutk_platform_lib_iotc = tutk.load_library(str(path.absolute()))
84c91,92
<         self.tutk_platform_lib: CDLL = tutk_platform_lib
---
>         self.tutk_platform_lib_av: CDLL = tutk_platform_lib_av
>         self.tutk_platform_lib_iotc: CDLL = tutk_platform_lib_iotc
108c116
<             self.tutk_platform_lib, udp_port=self.udp_port or 0
---
>             self.tutk_platform_lib_iotc, udp_port=self.udp_port or 0
114c122
<             self.tutk_platform_lib, max_num_channels=self.max_num_av_channels
---
>             self.tutk_platform_lib_av, max_num_channels=self.max_num_av_channels
126,127c134,135
<         tutk.av_deinitialize(self.tutk_platform_lib)
<         tutk.iotc_deinitialize(self.tutk_platform_lib)
---
>         tutk.av_deinitialize(self.tutk_platform_lib_av)
>         tutk.iotc_deinitialize(self.tutk_platform_lib_iotc)
132c140
<         return tutk.iotc_get_version(self.tutk_platform_lib)
---
>         return tutk.iotc_get_version(self.tutk_platform_lib_iotc)
161c169
<         return WyzeIOTCSession(self.tutk_platform_lib, account, camera)
---
>         return WyzeIOTCSession(self.tutk_platform_lib_av, self.tutk_platform_lib_iotc, account, camera)
233c241,242
<         tutk_platform_lib: CDLL,
---
>         tutk_platform_lib_av: CDLL,
>         tutk_platform_lib_iotc: CDLL,
252c261,262
<         self.tutk_platform_lib: CDLL = tutk_platform_lib
---
>         self.tutk_platform_lib_av: CDLL = tutk_platform_lib_av
>         self.tutk_platform_lib_iotc: CDLL = tutk_platform_lib_iotc
275c285
<             self.tutk_platform_lib, self.session_id
---
>             self.tutk_platform_lib_iotc, self.session_id
301c311
<         return TutkIOCtrlMux(self.tutk_platform_lib, self.av_chan_id)
---
>         return TutkIOCtrlMux(self.tutk_platform_lib_iotc, self.tutk_platform_lib_av, self.av_chan_id)
357c367
<                 self.tutk_platform_lib, self.av_chan_id
---
>                 self.tutk_platform_lib_av, self.av_chan_id
626c636
<             session_id = tutk.iotc_get_session_id(self.tutk_platform_lib)
---
>             session_id = tutk.iotc_get_session_id(self.tutk_platform_lib_iotc)
632c642
<                 self.tutk_platform_lib, self.camera.p2p_id, self.session_id
---
>                 self.tutk_platform_lib_iotc, self.camera.p2p_id, self.session_id
642c652
<                 self.tutk_platform_lib,
---
>                 self.tutk_platform_lib_av,
667c677
<         tutk.av_client_set_max_buf_size(self.tutk_platform_lib, max_buf_size)
---
>         tutk.av_client_set_max_buf_size(self.tutk_platform_lib_av, max_buf_size)
724c734
<             tutk.av_client_stop(self.tutk_platform_lib, self.av_chan_id)
---
>             tutk.av_client_stop(self.tutk_platform_lib_av, self.av_chan_id)
727c737
<             tutk.iotc_session_close(self.tutk_platform_lib, self.session_id)
---
>             tutk.iotc_session_close(self.tutk_platform_lib_iotc, self.session_id)

wyzecam/tutk/tutk_ioctl_mux.py

109c109
<     def __init__(self, tutk_platform_lib: CDLL, av_chan_id: c_int) -> None:
---
>     def __init__(self, tutk_platform_lib_iotc: CDLL, tutk_platform_lib_av: CDLL, av_chan_id: c_int) -> None:
116c116,117
<         self.tutk_platform_lib = tutk_platform_lib
---
>         self.tutk_platform_lib_iotc = tutk_platform_lib_iotc
>         self.tutk_platform_lib_av = tutk_platform_lib_av
122c123
<             tutk_platform_lib, av_chan_id, self.queues
---
>             tutk_platform_lib_av, av_chan_id, self.queues # original iotc
189c190
<             self.tutk_platform_lib, self.av_chan_id, ctrl_type, encoded_msg
---
>             self.tutk_platform_lib_av, self.av_chan_id, ctrl_type, encoded_msg
kroo commented 3 years ago

Thanks! Many of the Linux and mac distributions of the library are separated into separate av vs iotc libraries as well; I think if you specified the same library twice it would work with your changes as well. Let me see if I can put this into a set of changes that work across all platforms.

a904guy commented 3 years ago

I think I could modify the source to work with windows natively using Win32/X64 .dll files without changing how any of the main functionality works. Just some modifications to tulk.py

I've been testing using .dll inclusions instead of the .so inclusions and see they function in a similar manner and are named the same calls, they just come from various .dlls instead of a single .so file.

Here is a quick check locating IOTC_Connect_ByUID image

Then accessing the functions is the same as the wyze-cam package tutk.py file. I'm calling three different functions, from three different DLLs. P2PTunnelAgentInitialize, IOTC_Initialize2, avInitialize image image

Just would require two changes to how the script operates.

Inside of tulk.py

First Change We'd need to make it check OS and either call the .so files or the .dll files as required, simple enough os.name check. If windows, we just load all the DLLs into a dictionary, instead of just the main variable inside of Load_Library call.

Second Change Foreach call to the lib, we just modify it to either work off the .so lib or from the appropriate DLL.

@kroo
Would you be interested in this as an update to the wyzecam package?

TACIXAT commented 10 months ago

This command worked for me in a developer console.

link /LTCG /DLL /OUT:IOTCAPIs_ALL.dll /WHOLEARCHIVE:AVAPIs_s.lib /WHOLEARCHIVE:IOTCAPIs_s.lib legacy_stdio_definitions.lib

Fighting with the login now, getting a 403 forbidden. If I get it running I will update.