I’ll start off by making is clear that I’m not advocating for others to adopt this approach. It’s overly reliant on far too many moving parts to be of general practical use and it depends on a number of work arounds. However, some parts of this may be useful to others so I’ll post it here.
I have a couple of Wyze cameras. I’d like to be able to see stills every ten seconds or so on my MainUI page so I can quickly check to see if the door is open and verify it’s safe to open/close the door.
However, Wyze doesn’t supply an API (which is a shame because I bet there are thousands on this very forum who would buy their devices if there were a binding). They do supply an alternative firmware that enables local access to an RTSP stream but that firmware is not kept up to date and it can cause havoc on your local network. All of the reverse engineered and cracked firmwares have been abandoned. And if you use this firmware, you have to give up on access to any new features or services Wyze provides.
You may have better luck with the alternative firmware. But I’m stubborn and wanted to have access to the streams with the stock firmware.
Unfortunately all the big players in CCTV software such as ZoneMinder, Shinobi, or BlueIris all require one to replace the firmware to enable the RTSP stream. But there is one CCTV program that can access the Wyze camera stream through Wyze’s cloud service, TinyCam Pro.
The problem with TinyCam Pro is it’s an Android only app.
- Install Android into a VM with Tasker and droid-VNC-NG for some convenience
- Install TinyCam Pro onto that VM
- Configure TinyCam Pro to access the Wyze Cameras (note if you are still on a Nest account it can also connect to Nest Hello and Nest cameras)
- Configure TinyCam Pro’s recording and notification capabilities
- Configure openHAB’s IP Camera binding
- Future work/possibilities
I already have an ESXi server so it made the most sense for me to install Android in a VM using https://www.android-x86.org/. This is based on LineageOS 14.1 which is Android version 7. While that’s not great it’s adequate for our purposes. However, alternative approaches include:
|Use an old Android phone or tablet||Less work up front||Awkward form factor, uncomfortable running a server on completely unsupported software|
|Use Android on an RPi||Requires a screen, keyboard and mouse or touch screen to set up and configure, no headless config||Requires an RPi 3 or RPi 4|
|Put it on your “production” phone||Less work up front||Disables the camera feed when not on the LAN or end up using lots of mobile data constantly streaming video|
|Virtual Machine on a server||Always running and on local RAM, more power than a typical phone||Probably not the best choice unless already running VMs as it’s a lot of work to get set up initially.|
As is clear, I chose the VM option.
I’m running ESXi 6.7 so I followed the instructions at How to Install Android on VMware: A Step-by-Step Guide. Some places where I deviated from those instructions:
- I downloaded and used the 14.1-r5 64-bit ISO file.
- The OS type was "Other 4.x or later Linux (64-bit).
- I gave the VM more local storage than 8 GB, this is after all going to become a CCTV server.
- I also gave the virtual video card a bit more memory, though I don’t know if that does anything worth while.
- When you get to the GRUB menu what you need to do differs slightly from that tutorial. You do need to edit the first entry as described but after making the changes (i.e. replacing “quiet” with “nomodeset xforcevesa”) you need to hit ENTER. Then hit “b” to boot to the newly edited boot config. This will not be saved.
- Pressing CTRL-F1 to open a terminal didn’t work for me, probably because I’m using the ESXi console and the local OS captures the keypresses. So to edit the grub config as described I just rebooted the VM without making changes to the GRUB entry. That prevents the GUI from loaded and gives you a command prompt. There is a Terminal Emulator app which I discovered later that might have also worked without the reboot.
Once you are up and running one of the first things you’ll want to do is prevent the VM from going to sleep. There is no need and it’s a pain to swipe up with the mouse to wake it up. To do this you need to enable the Developer options menu. Open Settings → About Tablet and click on the build number entry seven times. Then you can back up and go into the new Developer options menu and turn off Sleep by toggling on “Stay awake”.
Go through the menu and enable, disable any other settings desired.
Now go through the apps and remove/disable any that you don’t need like the phone app.
If you use static IPs, now is the time to configure the DHCP server or configure a static IP in the WiFi settings of the VM.
You do not need Tasker for this. For an app it’s on the expensive side but if you already have paid for it there is no reason not to use it. In this case one of the problems is that we do not have VM Tools installed and we don’t have a physical power button. So the only way to reboot the VM is to do the equivalent of yanking the power. So I create a task in Tasker to reboot the phone and added a shortcut to that on the desktop. Add one for shutdown too if desired.
This is an app that installs a VNC server on Android and it doesn’t even require root which is nice. This will make it easier to remotely access the VM/computer. It can be found in the Play store or any of the alternative app stores you may prefer.
However note the limitations, it will only work with the soft keyboard in Android and not work with keyboard events from a VNC client. So make sure to keep the keyboard app enabled.
I’ve actually not played with this much as I’m OK accessing it through the ESXi UI.
Install TinyCam Pro. It has been so long I don’t remember the difference between the free and paid app. I use the paid app.
I’m not going to go through everything. There are docs for that. I’m just going to touch on the outlines of the configuration.
- Go to “Manage cameras”
- Click the + icon to create a camera and select “Add IP camera, NVR/DVR”. Note that TinyCam can be used to turn an android phone into a WiFi camera and there is some network discovery built in.
- Give the camera a name and select Wyze Labs as the Camera brand. Select the model of your camera. Keep the protocol as Cloud (if you have RTSP you can skip all this and use the IP Camera Addon in OH for all of this). Enter your Wyze account credentials and under Advanced settings you’ll need to select the camera feed. In my experience you’ll need to figure out which camera goes with which number feed via trial and error.
- Set all your preferred recording settings. I use 8 GB for the recording quota and I’ve a NextCloud service configured for cloud recording. I will probably adjust this as time goes on to keep just a couple days worth of recordings. You can also record to an FTP server on your LAN which might be easier to set up. You will want to get the recordings off the “tablet” for ease of access one way or the other.
- Review and set any Motion Detection and Audio settings desired. Note we will be coming back to configure the Webhook on motion later.
Repeat for each camera you want to use with TinyCam Pro.
Additional settings to consider:
- Under “UI & Behavior” turn on “Auto start sequence mode on live view” to automatically rotate between the cameras, turn on “Auto start live view on boot”, turn on “Auto start background mode on boot” and turn on “Auto start web server on boot”.
- If you are on physical hardware, you might get some improvement by using Hardware for the H.264/H.265 decoder under “Video settings”.
- Under “Recording settings” there are options to set the size of each video size and how much time before and after a motion event to record (only available when background mode is on).
- Under “Web server” you will need to configure a password for the admin user and/or the Guest user.
- Make sure that the Web server is turned on. It will tell you it’s running in a notification and in the UI with the URI for the server.
My needs for these cameras in openHAB are very modest. All I want is to show the view with a refresh rate of around 10 seconds. There is a ton more one can do with the IP Camera add-on.
- Install the binding
- Create an RTSP/HTTP IP Camera Thing
- Enter all the relevant configuration settings.
- IP Address: hostname or IP address of the Android VM
- Port: 8083 unless changed in TinyCam Pro
- Snapshot URL:
http://<ip address>:<port>/axis-cgi/jpg/image.cgi?camera=<TinyCam Pro camera number>
- MJPEG URL:
http://<ip address>:<port>/axis-cgi/mjpg/video.cgi?camera=<TinyCam Pro camera number>
- Server Port: a unique number not already in use on this machine, each camera needs it’s own port number
guestdepending on how you configured the webserver access in TinyCam Pro
- Password: password that corresponds with the username
- Poll Time: smaller number means more resources
- Update Image Channel When: Image channel follows pollImage
I am running in Docker so don’t really have access to ffmpeg so didn’t do much there. Here is an example Thing.
UID: ipcamera:generic:garage label: Garage Camera thingTypeUID: ipcamera:generic configuration: mjpegOptions: -q:v 5 -r 2 -vf scale=640:-2 -update 1 ipAddress: arachne mjpegUrl: http://arachne:8083/axis-cgi/mjpg/video.cgi?camera=1 updateImageWhen: "1" gifPreroll: 0 ffmpegLocation: /usr/bin/ffmpeg serverPort: 9999 ffmpegOutput: /etc/openhab/html/camera1/ ipWhitelist: DISABLE mp4OutOptions: -c:v copy -c:a copy pollTime: 10000 password: password port: 8083 snapshotUrl: http://arachne:8083/axis-cgi/jpg/image.cgi?camera=1 snapshotOptions: -an -vsync vfr -q:v 2 -update 1 username: admin ffmpegInput: http://arachne:8083/axis-cgi/mjpg/video.cgi?camera=1 hlsOutOptions: -strict -2 -f lavfi -i aevalsrc=0 -acodec aac -vcodec copy -hls_flags delete_segments -hls_time 2 -hls_list_size 4 gifOutOptions: -r 2 -filter_complex scale=-2:360:flags=lanczos,setpts=0.5*PTS,split[o1][o2];[o1]palettegen[p];[o2]fifo[o3];[o3][p]paletteuse
Given my use case I’ve only linked Items to two of the Channels.
|Switch||Poll Image||When ON the binding will poll for the latest frame from the camera based on the Poll Time setting|
|Image||Image||When the Poll Image Item is ON, it will be populated with the actual latest image from the camera based on the Poll Time setting|
If all went to plan the Image Item will start to be set to the camera feed periodically when the Switch is turned ON.
To show how I’m using this here is the widget I created to put on my overview page.
This shows the camera in the Garage and lets me trigger the garage door openers.
NOTE: Make sure the date/time get’s stamped on the images in the Wyze app or in TinyCam Pro so you can tell if you are looking at a recent view.
uid: garage_widget tags: - card - garage props: parameters:  parameterGroups:  timestamp: Feb 12, 2021, 10:02:20 AM component: f7-card config: title: Garage Doors slots: default: - component: f7-row slots: default: - component: oh-image config: item: GarageCamera_Image style: width: 100% height: auto - component: f7-row config: class: - justify-content-left slots: default: - component: f7-col slots: default: - component: oh-label-card config: footer: Small Garage Door Opener action: command actionItem: Small_Garagedoor_Opener actionCommand: ON label: '=(items.Small_Garagedoor_Sensor.state == "OPEN") ? "close" : "open"' item: Small_Garagedoor_Sensor icon: '=(items.Small_Garagedoor_Sensor.state == "CLOSED") ? "f7:house" : "f7:house_fill"' iconColor: '=(items.Small_Garagedoor_Sensor.state == "CLOSED") ? "green" : "orange"' - component: f7-col slots: default: - component: oh-label-card config: footer: Large Garage Door Opener action: command actionItem: Large_Garagedoor_Opener actionCommand: ON label: '=(items.Large_Garagedoor_Sensor.state == "OPEN") ? "close" : "open"' icon: '=(items.Large_Garagedoor_Sensor.state == "CLOSED") ? "f7:house" : "f7:house_fill"' iconColor: '=(items.Large_Garagedoor_Sensor.state == "CLOSED") ? "green" : "orange"'
Create a String Item for each camera which will receive the motion events from TinyCam Pro. I’ll use
Next navigate to each camera’s settings and open the Motion detection settings. Configure the Webhook on motion setting to
http://<ip of openHAB>:8080/static/tinycam.html?item=<item name>&motion=%MOTION_TYPE%
<ip of openHAB> is the IP or hostname of the openHAB server and ` is the name of the Item that captures the motion detections from this camera.
Copy the following into
$OH_CONF/html/tinycam.html. This will be a web page that will receive the GET request from TinyCam, parse out the arguments in the address and command the item with the value of motion.
NOTE: This is really easy to make generic to support converting any HTTP GET request to an Item command or update. I might post a separate tutorial on that.
You will need to modify the URL to be the path to your openHAB instance. Note that this will be executed on the caller’s machine so that needs to be the URL that TinyCam can use to reach openHAB.
There may be other cases where the only way a device can be interacted with is through its Android app. This approach could be use to host that app and then use Tasker and various Tasker add-ons like AutoNotification and AutoInput or it’s relatively new ability to read and react to the system log to interact with the device’s Android app and send/receive information from openHAB.
That of course is an exercise for the reader.