# -*- coding: utf-8 -*-

'''
Make sure your device is connected to the same network as ESP32-CAM
Change the network variables and run this code on your PC
Tested with Python 3.8
'''

import requests
import base64
from time import sleep, time

#####
# change these variables here !
IP = '192.168.178.37' #address for esp32-cam
NAME = 'your_name' #match username on server
#####

URL = 'https://your_name.pythonanywhere.com/'
STREAM_TARGET = URL+NAME+'/post_frame'
COMMAND_TARGET = URL+NAME+'/get_command'
s_esp32 = requests.session()
s_server = requests.session()

def get_command():
    #get new commands from cloud
    r = s_server.get(COMMAND_TARGET)
    rec = r.content.decode('utf-8')
    #send to esp32 if available
    if not rec:
        print ('<< no command from server')
        return
    print ('<< command: ', rec, 'received')
    r = s_esp32.get('http://'+IP+'/control', params = {'var': 'key', 'val':int(rec)})
    print ('post to esp32 status: ', r.status_code)

def stream():
    r = requests.get('http://'+IP+':81/stream', stream=True)
    if(r.status_code == 200):
        counter = 0
        last_frame = time()
        img_bytes = bytes()
        for chunk in r.iter_content(chunk_size=1024):
            img_bytes += chunk
            a = img_bytes.find(b'\xff\xd8')
            b = img_bytes.find(b'\xff\xd9')
            if a != -1 and b != -1:
                jpg = img_bytes[a:b+2]
                img_bytes = img_bytes[b+2:]
                # do not send if it is an old frame
                if (time() - last_frame) < 0.3:
                    continue
                # encode image as base64
                jpg_as_text = base64.b64encode(jpg).decode('utf-8')
                if (len(jpg_as_text) == 0):
                    continue
                # increment counter
                last_frame = time()
                counter += 1
                print ('loop', counter, ': ')
                # post to server
                print ('>> sending', type(jpg_as_text), 'of length', len(jpg_as_text))
                response = s_server.post(STREAM_TARGET, data=jpg_as_text)
                print(response.text)
                # get new commands from server
                get_command()
                print ('\n')
                #sleep(0.1)
    else:
        print("Error: unexpected status code {}".format(r.status_code))

try:
    stream()
except Exception as e:
    print ('Error: ', str(e))
    s_esp32.close()
    s_server.close()