• 1
    Raspberry pi setup

    First of all, install Raspbian on a micro SD card and put it into your pi.

    If you don't feel like connecting your pi to a monitor, you can set it up by simply reinserting the micro sd into you computer and add a file named 'ssh' to the boot folder. Then add a file named 'wpa-supplicant.conf' with the your wifi settings, so that the pi will automatically connect to it. Check out what to put in the wpa-supplicant file here. Once that is done, you can check you router to get the IP of your pi and use putty to connect to it.

    I recommend you change the default password of the pi, since this will be connected to the internet (default credentials for raspbian: pi, raspberry).

    On the home file (/pi/home) of your pi, create startup.sh.

    You can use 'nano startup.sh' to create the file and edit it. I don't usually use nano, but since the is two lines of code and you might not be used to vim or other text editor, nano is simple. In startup.sh (or whatever you feel like naming it), type this:

    sudo systemctl enable ssh
    sudo systemctl start ssh

     Press ctrl+x to save the file. Later we will add this file to a crontab to run it on startup. I have found that sometimes the raspberry pi after being shutdown doesn't re-enable ssh and it can be a pain to re-add the 'ssh' file on the micro sd everytime.

  • 2
    The Code

    On the home file (/pi/home) of your pi, lightSensor.py and VeSyncApi,py.

    For the lightSensor.py and VeSyncApi,py, I'll put my code here. You can either copy paste it and be done with it, but I encourage you to modify the lightSendor.py file to suit your needs and you might need to code you own API if you aren't using the same smart plug as me.


    import requests
    import hashlib
    import json
    import datetime
    import urllib3
    class Vesync:
        BASE_URL = "https://smartapi.vesync.com"
        username = "_yourUsernameOrEmail_"
        password = "_yourPassword_"
        _account = ""
        def __init__(self):
            print("class initialized")
        def connect(self):
            payload = json.dumps(
                {"account": self.username, "devToken": "",
                 "password": hashlib.md5(self.password.encode('utf-8')).hexdigest()})
            self._account = requests.post(self.BASE_URL + "/vold/user/login", verify=False, data=payload).json()
            if "error" in self._account:
                print("connection failed")
        def get_devices(self):
            return requests.get(self.BASE_URL + '/vold/user/devices', verify=False, headers=self.get_headers()).json()
        def turn_on(self, device_id, device_name):
            requests.put(self.BASE_URL + '/v1/wifi-switch-1.3/' + device_id + '/status/on', verify=False, data={}, headers=self.get_headers())
            print(device_name + " turned On")
        def turn_off(self, device_id, device_name):
            requests.put(self.BASE_URL + '/v1/wifi-switch-1.3/' + device_id + '/status/off', verify=False, data={}, headers=self.get_headers())
            print(device_name + " turned Off")
        def get_headers(self):
            return {'tk': self._account["tk"], 'accountid': self._account["accountID"]}
        def get_current_time_decimal(self):
            time = datetime.datetime.now()
            minutes = int(time.strftime("%M")) / 60
            hour = int(time.strftime("%H"))
            return hour + minutes

     In this file, you'll need to replace the username and password variable to the credentials you use on the VeSync mobile app to control your devices.


    import VeSyncApi as Api
    import RPi.GPIO as GPIO
    GPIO.setup(4, GPIO.IN)
    api = Api.Vesync()
    devices = api.get_devices()
    sensorStatus = GPIO.input(4)
    time = api.get_current_time_decimal()
    for device in devices:
        cid = device["cid"]
        status = device["deviceStatus"]
        name = device["deviceName"]
        if status == "on" and time <= 0.1:
            api.turn_off(cid, name)
        if status == "off" and sensorStatus == 1 and 16.5 < time < 21:
            api.turn_on(cid, name)

    If you change the name of VeSyncApi.py, be sure to change the import to the correct name. The RPi.GPIO pat only works on the raspberry pi, it checks whether there is current of not on a given GPIO pin. If the value of GPIO.input(4) is 1, that means its dark and if it's 0, then there is enough light.

    Here I am looping through all my device, but you can add code to only control a device with a certain Id or name. My first if closes the lights in my room just past midnight and the second if turns them on when it dark, the time is between 16h30 and 21h00 and the lights are currently off.

    The time is in 24h format and the minutes are given in decimal, so 30 min = 0.5.

    Finally, type 'sudo crontab -e' to schedule tasks and add these two lines in the file:

    @reboot sh /home/pi/startup.sh
    */5 * * * * /usr/bin/python /home/pi/lightSensor.py

     The first line, will make sure that ssh is enabled at reboot using our little .sh script
    The second line will run our lightSensor.py code every 5 min. I put 5 min, so that light changes will be detect often enough, but not to that point that putting your finger on top of the sensor triggers the code and faster then that is not a good idea for network traffic in general (even though this isn't really a heavy request)

  • 3
    Solder the components together

    Using this tutorial, connect three wires to the appropriate pins (or holes) on the pi and on the light sensor. The pins/holes placement is the same on all raspberry pi models. On the light sensor, the pins should be labeled. There is the 3.3V pin, the ground and the signal pi. Soldering on the raspberry pi is difficult and you can break it if you are not careful (DON'T spill soldering metal in the circuits :P). Once the cables are soldered on the pi, solder the other end of each on the photosensor module.

    This is optional, but since I wanted everything to fit nicely into the raspberry pi zero camera case, with the photosensor pointing out the camera hole, I had to cut off the pins from the photosensor module to solder the wires closer to the board so it would take less space. This proved to be very difficult since, once the pins removed, the solder wasn't holding on to the little bits of the pins still poking out from the board. It eventually worked but it was very sloppy work and I was afraid that the solder would come off while I was folding the cables to fit everything in the case.

    Before closing the case, play with the dial on the photosensor using a screwdriver and run the code manually through putty so that the photosensor send the signals are the right amount of light. This requires fine tuning and a lot of testing to get it right.

    If you get the same photosensor model as me, there should be two lights on it. One is always on and one lights up when it's two bright only (i think... it might be the opposite). Once everything is powered up, place you pi pretty much where you want it to get the same lighting and play around with the dial until the threshold seems fine.

    Finally, place everything in the case, close it, and stick it on the wall (I fixed mine with Velcro to easily remove it)(also, I used electric tape to position the photosensor in the top of the case, it's messy but it works). You'll have to power it up with micro USB cable, so it can look quite ugly, but I put mine next to a thermostat and I passed a long micro USB cable into the wall from behind the thermostat to a hole next to a plug.