├── firmwares-20230607 ├── BLE │ ├── README.md │ └── firmware.bin ├── BTC │ ├── README.md │ └── firmware.bin ├── WIFI+TLS │ ├── README.md │ └── firmware.bin └── README.md ├── firmware.bin ├── examples ├── README.md └── streaming-to-opencv │ ├── video_streaming.py │ └── README.md ├── IMG_20220613_231019-01.jpeg ├── firmware-20221121 ├── firmware.bin └── README.md ├── firmware-20221203 ├── firmware.bin └── README.md ├── firmwares-20230521 ├── BLE │ ├── firmware.bin │ ├── README.md │ └── example │ │ ├── ble_cam.py │ │ ├── README.md │ │ └── esp32_ble.py ├── BTC │ ├── firmware.bin │ └── README.md ├── WIFI+TLS │ ├── firmware.bin │ └── README.md ├── scripts │ ├── README.md │ ├── config.py │ └── webcam.py ├── SDcard │ ├── README.md │ └── test_sdcard.py └── README.md ├── Christmas-2023-Edition ├── images │ ├── Back.jpg │ └── Front.jpg ├── esp32 │ └── firmware.bin ├── scripts │ ├── test_color.py │ ├── test_gray.py │ └── cam_config.py └── README.md ├── X23 ├── esp32-aiThinker │ ├── firmwares │ │ ├── ble │ │ │ └── firmware.bin │ │ ├── btc │ │ │ └── firmware.bin │ │ └── wifi+ssl │ │ │ └── firmware.bin │ ├── scripts │ │ ├── auth.py │ │ ├── cam_config.py │ │ └── streaming_server.py │ └── tests │ │ ├── test_color.py │ │ ├── test_gray.py │ │ └── config_test.py ├── esp32s3-xiao │ ├── firmwares │ │ ├── wifi+ssl │ │ │ └── firmware.bin │ │ └── wifi+ssl+ble │ │ │ └── firmware.bin │ ├── scripts │ │ ├── auth.py │ │ ├── cam_config.py │ │ └── streaming_server.py │ └── tests │ │ └── config_test.py ├── esp32s3-freenove │ ├── firmwares │ │ ├── wifi+ssl │ │ │ └── firmware.bin │ │ └── wifi+ssl+ble │ │ │ └── firmware.bin │ ├── scripts │ │ ├── auth.py │ │ ├── cam_config.py │ │ └── streaming_server.py │ ├── tests │ │ ├── sdcard_test.py │ │ └── config_test.py │ └── notes │ │ └── README.md ├── esp32s3-lilygo │ ├── firmwares │ │ ├── wifi+ssl │ │ │ └── firmware.bin │ │ └── wifi+ssl+ble │ │ │ └── firmware.bin │ ├── notes │ │ └── LILYGO-T-CAMERA-S3_12.jpg │ ├── scripts │ │ ├── auth.py │ │ ├── pmu.py │ │ ├── cam_config.py │ │ └── streaming_server.py │ └── tests │ │ ├── oled_test_1.py │ │ ├── oled_test.py │ │ └── config_test.py ├── opencv_scripts │ ├── client.py │ ├── face_detection.py │ └── hands_detection.py └── README.md ├── firmwares-20230717 ├── ESP32 │ ├── README.md │ └── AI-Thinker-OV2640 │ │ ├── BLE │ │ └── firmware.bin │ │ ├── BTC │ │ └── firmware.bin │ │ ├── WiFi-SSL │ │ ├── firmware.bin │ │ └── README.md │ │ ├── README.md │ │ └── scripts │ │ ├── streaming_client.py │ │ ├── Wifi.py │ │ └── streaming_server.py ├── ESP32-S3 │ ├── Freenove-OV2640 │ │ ├── WiFi │ │ │ └── firmware.bin │ │ ├── IMG_20230717_173345.jpg │ │ ├── WiFi+BLE │ │ │ └── firmware.bin │ │ └── README.md │ ├── XIAO-Sense-OV2640 │ │ ├── WiFi │ │ │ └── firmware.bin │ │ ├── WiFi+BLE │ │ │ └── firmware.bin │ │ ├── IMG_20230717_173528.jpg │ │ ├── scripts │ │ │ ├── License.txt │ │ │ ├── streaming_client.py │ │ │ ├── Wifi.py │ │ │ └── streaming_server.py │ │ └── README.md │ ├── LILYGO-T-Camera-OV2640 │ │ ├── WiFi │ │ │ └── firmware.bin │ │ ├── WiFi+BLE │ │ │ └── firmware.bin │ │ ├── IMG_20230717_173425.jpg │ │ ├── scripts │ │ │ ├── pmu.py │ │ │ ├── License.txt │ │ │ ├── streaming_client.py │ │ │ ├── Wifi.py │ │ │ └── streaming_server.py │ │ └── README.md │ └── README.md ├── README.md ├── scripts │ ├── wifi.py │ ├── html.py │ ├── help.py │ ├── webcam.py │ └── site.py └── Note.md ├── LICENSE ├── wifi.py ├── html.py ├── webcam.py ├── help.py └── site.py /firmwares-20230607/BLE/README.md: -------------------------------------------------------------------------------- 1 | Firmware with BLE support 2 | -------------------------------------------------------------------------------- /firmwares-20230607/BTC/README.md: -------------------------------------------------------------------------------- 1 | Firmware with Bluetooth Classic support 2 | -------------------------------------------------------------------------------- /firmwares-20230607/WIFI+TLS/README.md: -------------------------------------------------------------------------------- 1 | Firmware with Wifi and SSL support 2 | -------------------------------------------------------------------------------- /firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmware.bin -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | In this directory, I'll put some sample scripts that others might find useful. 2 | -------------------------------------------------------------------------------- /IMG_20220613_231019-01.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/IMG_20220613_231019-01.jpeg -------------------------------------------------------------------------------- /firmware-20221121/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmware-20221121/firmware.bin -------------------------------------------------------------------------------- /firmware-20221203/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmware-20221203/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230521/BLE/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230521/BLE/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230521/BTC/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230521/BTC/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230607/BLE/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230607/BLE/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230607/BTC/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230607/BTC/firmware.bin -------------------------------------------------------------------------------- /Christmas-2023-Edition/images/Back.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/Christmas-2023-Edition/images/Back.jpg -------------------------------------------------------------------------------- /Christmas-2023-Edition/images/Front.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/Christmas-2023-Edition/images/Front.jpg -------------------------------------------------------------------------------- /Christmas-2023-Edition/esp32/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/Christmas-2023-Edition/esp32/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230521/WIFI+TLS/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230521/WIFI+TLS/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230607/WIFI+TLS/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230607/WIFI+TLS/firmware.bin -------------------------------------------------------------------------------- /X23/esp32-aiThinker/firmwares/ble/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/X23/esp32-aiThinker/firmwares/ble/firmware.bin -------------------------------------------------------------------------------- /X23/esp32-aiThinker/firmwares/btc/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/X23/esp32-aiThinker/firmwares/btc/firmware.bin -------------------------------------------------------------------------------- /X23/esp32s3-xiao/firmwares/wifi+ssl/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/X23/esp32s3-xiao/firmwares/wifi+ssl/firmware.bin -------------------------------------------------------------------------------- /X23/esp32-aiThinker/firmwares/wifi+ssl/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/X23/esp32-aiThinker/firmwares/wifi+ssl/firmware.bin -------------------------------------------------------------------------------- /X23/esp32s3-freenove/firmwares/wifi+ssl/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/X23/esp32s3-freenove/firmwares/wifi+ssl/firmware.bin -------------------------------------------------------------------------------- /X23/esp32s3-lilygo/firmwares/wifi+ssl/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/X23/esp32s3-lilygo/firmwares/wifi+ssl/firmware.bin -------------------------------------------------------------------------------- /X23/esp32s3-lilygo/notes/LILYGO-T-CAMERA-S3_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/X23/esp32s3-lilygo/notes/LILYGO-T-CAMERA-S3_12.jpg -------------------------------------------------------------------------------- /X23/esp32s3-xiao/firmwares/wifi+ssl+ble/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/X23/esp32s3-xiao/firmwares/wifi+ssl+ble/firmware.bin -------------------------------------------------------------------------------- /X23/esp32s3-lilygo/firmwares/wifi+ssl+ble/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/X23/esp32s3-lilygo/firmwares/wifi+ssl+ble/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230717/ESP32/README.md: -------------------------------------------------------------------------------- 1 | 2 | Currently only the AI-Thinker board is supported. The firmware is configured to support the AI-Thinker pin configuration by default. 3 | 4 | -------------------------------------------------------------------------------- /X23/esp32s3-freenove/firmwares/wifi+ssl+ble/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/X23/esp32s3-freenove/firmwares/wifi+ssl+ble/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230521/scripts/README.md: -------------------------------------------------------------------------------- 1 | New config.py configuration file for use with camera.conf(). Small modification to the webcam.py script. Everything else is the same as before. 2 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32/AI-Thinker-OV2640/BLE/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230717/ESP32/AI-Thinker-OV2640/BLE/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230717/ESP32/AI-Thinker-OV2640/BTC/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230717/ESP32/AI-Thinker-OV2640/BTC/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/Freenove-OV2640/WiFi/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230717/ESP32-S3/Freenove-OV2640/WiFi/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/XIAO-Sense-OV2640/WiFi/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230717/ESP32-S3/XIAO-Sense-OV2640/WiFi/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230717/ESP32/AI-Thinker-OV2640/WiFi-SSL/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230717/ESP32/AI-Thinker-OV2640/WiFi-SSL/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/Freenove-OV2640/IMG_20230717_173345.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230717/ESP32-S3/Freenove-OV2640/IMG_20230717_173345.jpg -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/Freenove-OV2640/WiFi+BLE/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230717/ESP32-S3/Freenove-OV2640/WiFi+BLE/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/XIAO-Sense-OV2640/WiFi+BLE/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230717/ESP32-S3/XIAO-Sense-OV2640/WiFi+BLE/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/LILYGO-T-Camera-OV2640/WiFi/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230717/ESP32-S3/LILYGO-T-Camera-OV2640/WiFi/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/XIAO-Sense-OV2640/IMG_20230717_173528.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230717/ESP32-S3/XIAO-Sense-OV2640/IMG_20230717_173528.jpg -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/LILYGO-T-Camera-OV2640/WiFi+BLE/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230717/ESP32-S3/LILYGO-T-Camera-OV2640/WiFi+BLE/firmware.bin -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/LILYGO-T-Camera-OV2640/IMG_20230717_173425.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython-2022/HEAD/firmwares-20230717/ESP32-S3/LILYGO-T-Camera-OV2640/IMG_20230717_173425.jpg -------------------------------------------------------------------------------- /firmwares-20230607/README.md: -------------------------------------------------------------------------------- 1 | Fix time module. 2 | 3 | ``` 4 | >>> import time 5 | >>> time. 6 | gmtime localtime mktime sleep 7 | sleep_ms sleep_us ticks_add ticks_cpu 8 | ticks_diff ticks_ms ticks_us time 9 | time_ns 10 | ``` 11 | -------------------------------------------------------------------------------- /firmwares-20230521/SDcard/README.md: -------------------------------------------------------------------------------- 1 | Some microSD cards may cause problems. What can happen is that your program hangs while writing to the card. 2 | The card works fine on a PC, but has writing problems with MicroPython. 3 | This utility script will help you to test such a problem with the microSD card you are using. 4 | -------------------------------------------------------------------------------- /X23/esp32-aiThinker/scripts/auth.py: -------------------------------------------------------------------------------- 1 | 2 | # connect to access point 3 | AP = const('SSID') # Your SSID 4 | PW = const('PASS') # Your password 5 | # WEB user - can change to whatever 6 | UID = const('ait') # authentication user 7 | PWD = const('Hi-AIT-123') # authentication password 8 | # URL with the above UID and PWD, eg 9 | # http://192.168.4.44/ait/Hi-AIT-123 10 | 11 | -------------------------------------------------------------------------------- /X23/esp32s3-freenove/scripts/auth.py: -------------------------------------------------------------------------------- 1 | 2 | # connect to access point 3 | AP = const('SSID') # Your SSID 4 | PW = const('PASS') # Your password 5 | # WEB user - can change to whatever 6 | UID = const('free') # authentication user 7 | PWD = const('Hi-Nove-La') # authentication password 8 | # URL with the above UID and PWD, eg 9 | # http://192.168.4.74/free/Hi-Nove-La 10 | 11 | -------------------------------------------------------------------------------- /X23/esp32s3-lilygo/scripts/auth.py: -------------------------------------------------------------------------------- 1 | 2 | # connect to access point 3 | AP = const('SSID') # Your SSID 4 | PW = const('PASS') # Your password 5 | # WEB user - can change to whatever 6 | UID = const('lily') # authentication user 7 | PWD = const('Hi-Lily-Goen') # authentication password 8 | # URL with the above UID and PWD, eg 9 | # http://192.168.4.71/lily/Hi-Lily-Goen 10 | 11 | -------------------------------------------------------------------------------- /X23/esp32s3-xiao/scripts/auth.py: -------------------------------------------------------------------------------- 1 | 2 | # connect to access point 3 | AP = const('SSID') # Your SSID 4 | PW = const('PASS') # Your password 5 | # WEB user - can change to whatever 6 | UID = const('xiao') # authentication user 7 | PWD = const('Hi-Xiao-Ling') # authentication password 8 | # URL with the above UID and PWD, eg 9 | # http://192.168.4.70/xiao/Hi-Xiao-Ling 10 | 11 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32/AI-Thinker-OV2640/README.md: -------------------------------------------------------------------------------- 1 | 2 | There are three versions of firmwares: 3 | 4 | 1. WiFi-SSL - With WiFi, Sockets and SSL 5 | 2. BLE - Includes BLE and no WiFi 6 | 3. BTC - With Bluetooth classic, without BLE and WiFi 7 | 8 | For more information, please refer to previous notes in this repository. 9 | 10 | These firmwares are not fully tested, my apologies in advance if they do not work as expected. 11 | -------------------------------------------------------------------------------- /firmware-20221121/README.md: -------------------------------------------------------------------------------- 1 | MicroPython v1.19.1-705-gac5934c96 2022-11-21 2 | 3 | Compiled with *esp-idf-442* 4 | 5 | What NOT include: 6 | 1. help 7 | 2. SSL 8 | 3. I2S 9 | 4. BLE 10 | 5. webrepl 11 | 6. machine.adc 12 | 7. machine.dac 13 | 14 | Camera module: 15 | 1. OV2640 AI Thinker board only 16 | 2. I2C peripheral to use for SCCB: i2c-port0 17 | 3. Camera task pinned to core: CAMERA_CORE1 18 | 4. camera_config.xclk_freq_hz=18000000 19 | 5. now include hmirror as camera.mirror() 20 | 21 | -------------------------------------------------------------------------------- /X23/esp32s3-freenove/tests/sdcard_test.py: -------------------------------------------------------------------------------- 1 | 2 | from machine import SDCard 3 | import os 4 | 5 | sd = SDCard(slot=1, cd=None, wp=None) 6 | sd.info() 7 | # (1006632960, 512) 8 | os.mount(sd, '/sd') 9 | 10 | import camera 11 | cam = camera.init() 12 | if not cam: 13 | print('Hard reset!!') 14 | from machine import reset 15 | reset() 16 | 17 | img = camera.capture() 18 | print('Image size:', len(img)) 19 | with open('/sd/img1.jpg', 'wb') as f: 20 | w = f.write(img) 21 | print('Bytes saved:', w) 22 | print(os.listdir('/sd')) 23 | # ['img1.jpg'] 24 | os.umount('/sd') 25 | camera.deinit() 26 | 27 | -------------------------------------------------------------------------------- /examples/streaming-to-opencv/video_streaming.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | dropped = 0 # drop frames count 4 | 5 | vid = cv2.VideoCapture('http://10.0.4.44/live') # open webcam capture 6 | 7 | while True: 8 | ret, frame = vid.read() # get frame-by-frame 9 | #print(vid.isOpened(), ret) 10 | if frame is not None: 11 | if dropped > 0: dropped = 0 # reset 12 | cv2.imshow('Video-44',frame) # display frame 13 | if cv2.waitKey(22) & 0xFF == ord('q'): # press q to quit 14 | break 15 | else: 16 | dropped += 1 17 | if dropped > 100: 18 | print("Server is down") 19 | break 20 | 21 | # Done, clear all resources 22 | vid.release() 23 | cv2.destroyAllWindows() 24 | print("Video stop") 25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/streaming-to-opencv/README.md: -------------------------------------------------------------------------------- 1 | It is simple to stream to a script running opencv-python module cv2 on a Linux (or Linux-like) PC. 2 | 3 | Start the webcam script on the esp32cam. 4 | 5 | ``` 6 | >>> import webcam 7 | ``` 8 | Just remember to enter your WiFi credentials at line 189 of webcam.py: 9 | 10 | ``` 11 | w = Sta() 12 | w.connect('YourSSID', 'YourPassword') 13 | ``` 14 | 15 | You can disable login by setting login to false by auth.on=False 16 | With login disabled, you can include 'import webcam' in main.py and the webcam will start automatically at boot time. 17 | 18 | Simply run the script 19 | ``` 20 | $ python3 video_streaming.py 21 | ``` 22 | on the Linux PC. All you have to do is change the IP address in the cv2.VideoCapture() 23 | 24 | To use the script, you must first install opencv-python. 25 | 26 | -------------------------------------------------------------------------------- /firmwares-20230521/WIFI+TLS/README.md: -------------------------------------------------------------------------------- 1 | Firmware with WiFI/SSL only, no bluetooth.BLE 2 | 3 | ``` 4 | MicroPython v1.20.0-39-g61b8e1b2d-kaki5 on 2023-05-20; ESP32 CAMERA w/SSL (KAKI5) with ESP32 5 | >>> import camera 6 | >>> camera. 7 | aecvalue aelevels agcgain brightness 8 | capture conf contrast deinit 9 | flip framesize init mirror 10 | pixformat quality saturation speffect 11 | whitebalance 12 | >>> img = camera.capture() 13 | >>> len(img) 14 | 69153 15 | >>> camera.framesize(13) 16 | >>> img = camera.capture() 17 | >>> len(img) 18 | 95050 19 | >>> import ssl 20 | >>> ssl. 21 | CERT_NONE CERT_OPTIONAL CERT_REQUIRED wrap_socket 22 | >>> import bluetooth 23 | Traceback (most recent call last): 24 | File "", line 1, in 25 | ImportError: no module named 'bluetooth' 26 | 27 | ``` 28 | -------------------------------------------------------------------------------- /firmwares-20230521/SDcard/test_sdcard.py: -------------------------------------------------------------------------------- 1 | import machine, uos 2 | from time import sleep 3 | 4 | slt = 1 # slot 0 use by flash memory (1: default) 5 | wid = 1 # sdmmc (sdio) - 1 bit at time (default). Either 1 or 4 6 | # Only Data0, Data1 line is not used, 7 | # so that the LED GPIO4 will not blink 8 | frq = 20000000 # defult:20000000 9 | #frq = 10000000 10 | sd=machine.SDCard(slot=slt, width=wid, freq=frq) 11 | 12 | uos.mount(sd, "/sd") 13 | 14 | for i in range(100): # 100 frames video 15 | print(gc.mem_free()) 16 | data = b'sfsdfsdfeqeqw12414asfasf33qrfsafq3r332rfsfsdff3r3232rgsdvdvwr3efes'*500 17 | if len(data) > 0: 18 | print('Frame:', i) 19 | fn = '/sd/pic-%03d.jpg'%i 20 | f = open(fn, 'wb') 21 | w=f.write(data) 22 | print(i,w,len(data)) 23 | f.close() 24 | del f 25 | sleep(0.5) 26 | 27 | uos.listdir("/sd") 28 | uos.umount("/sd") 29 | 30 | -------------------------------------------------------------------------------- /Christmas-2023-Edition/scripts/test_color.py: -------------------------------------------------------------------------------- 1 | from st7735M import TFT,TFTColor 2 | from machine import SPI,Pin,Signal 3 | from time import sleep 4 | import camera 5 | import cam_config as cc 6 | 7 | # set camera configuration 8 | cc.configure(camera, cc.ai_thinker) 9 | camera.conf(cc.PIXFORMAT,cc.PIXFORMAT_RGB565) # both pixformat and 10 | camera.conf(cc.FRAMESIZE,cc.FRAMESIZE_QQVGA) # framesize MUST before camera.init 11 | camera.init() 12 | 13 | # other setting after init 14 | camera.quality(12) 15 | spi = SPI(1, baudrate=60000000, polarity=0, phase=0) 16 | tft=TFT(spi,2,15,12) 17 | tft.init_7735(tft.GREENTAB80x160) 18 | tft.fill(TFT.BLACK) 19 | def display(): 20 | w,h=160-1,80-1 21 | s0=160*20*2 22 | sx=160*100*2 23 | loc=tft._setwindowloc 24 | take=camera.capture 25 | put=tft._writedata 26 | while True: 27 | img=take() 28 | loc((0,0),(w,h)) 29 | put(img[s0:sx]) 30 | 31 | display() 32 | -------------------------------------------------------------------------------- /Christmas-2023-Edition/scripts/test_gray.py: -------------------------------------------------------------------------------- 1 | from st7735M import TFT,TFTColor 2 | from machine import SPI,Pin,Signal 3 | from time import sleep 4 | import camera 5 | import cam_config as cc 6 | 7 | # set camera configuration 8 | cc.configure(camera, cc.ai_thinker) 9 | camera.conf(cc.PIXFORMAT,cc.PIXFORMAT_RGB565) # both pixformat and 10 | camera.conf(cc.FRAMESIZE,cc.FRAMESIZE_QQVGA) # framesize MUST before camera.init 11 | camera.init() 12 | 13 | # other setting after init 14 | camera.quality(12) 15 | camera.speffect(2) # black and white 16 | spi = SPI(1, baudrate=60000000, polarity=0, phase=0) 17 | tft=TFT(spi,2,15,12) 18 | tft.init_7735(tft.GREENTAB80x160) 19 | tft.fill(TFT.BLACK) 20 | def display(): 21 | w,h=160-1,80-1 22 | s0=160*20*2 23 | sx=160*100*2 24 | loc=tft._setwindowloc 25 | take=camera.capture 26 | put=tft._writedata 27 | while True: 28 | img=take() 29 | loc((0,0),(w,h)) 30 | put(img[s0:sx]) 31 | 32 | display() 33 | -------------------------------------------------------------------------------- /X23/esp32s3-lilygo/scripts/pmu.py: -------------------------------------------------------------------------------- 1 | 2 | from AXP2101 import * 3 | from machine import Pin, I2C 4 | 5 | def cam_power_on(): 6 | SDA = 7 7 | SCL = 6 8 | IRQ = 2 9 | I2CBUS = I2C(1, scl=Pin(SCL), sda=Pin(SDA)) 10 | # I2CBUS.scan() 11 | # [52, 60] 12 | PMU = AXP2101(I2CBUS, addr=AXP2101_SLAVE_ADDRESS) 13 | id = PMU.getChipID() 14 | if id != XPOWERS_AXP2101_CHIP_ID: 15 | print("PMU is not online...") 16 | else: 17 | print('getID:%s' % hex(PMU.getChipID())) 18 | 19 | # Set the working voltage of the camera, 20 | # --* please do not modify the parameters--* 21 | PMU.setALDO1Voltage(1800) # CAM DVDD 1500~1800 22 | PMU.enableALDO1() 23 | PMU.setALDO2Voltage(2800) # CAM DVDD 2500~2800 24 | PMU.enableALDO2() 25 | PMU.setALDO4Voltage(3000) # CAM AVDD 2800~3000 26 | PMU.enableALDO4() 27 | 28 | # TS Pin detection must be disable, otherwise it cannot be charged 29 | PMU.disableTSPinMeasure() 30 | 31 | 32 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/LILYGO-T-Camera-OV2640/scripts/pmu.py: -------------------------------------------------------------------------------- 1 | 2 | from AXP2101 import * 3 | from machine import Pin, I2C 4 | 5 | def cam_power_on(): 6 | SDA = 7 7 | SCL = 6 8 | IRQ = 2 9 | I2CBUS = I2C(1, scl=Pin(SCL), sda=Pin(SDA)) 10 | # I2CBUS.scan() 11 | # [52, 60] 12 | PMU = AXP2101(I2CBUS, addr=AXP2101_SLAVE_ADDRESS) 13 | id = PMU.getChipID() 14 | if id != XPOWERS_AXP2101_CHIP_ID: 15 | print("PMU is not online...") 16 | else: 17 | print('getID:%s' % hex(PMU.getChipID())) 18 | 19 | # Set the working voltage of the camera, 20 | # --* please do not modify the parameters--* 21 | PMU.setALDO1Voltage(1800) # CAM DVDD 1500~1800 22 | PMU.enableALDO1() 23 | PMU.setALDO2Voltage(2800) # CAM DVDD 2500~2800 24 | PMU.enableALDO2() 25 | PMU.setALDO4Voltage(3000) # CAM AVDD 2800~3000 26 | PMU.enableALDO4() 27 | 28 | # TS Pin detection must be disable, otherwise it cannot be charged 29 | PMU.disableTSPinMeasure() 30 | 31 | -------------------------------------------------------------------------------- /X23/esp32-aiThinker/tests/test_color.py: -------------------------------------------------------------------------------- 1 | from st7735f import TFT,TFTColor 2 | from machine import SPI,Pin,reset 3 | from time import sleep 4 | import camera 5 | import cam_config as cc 6 | 7 | # set camera configuration 8 | cc.configure(camera, cc.ai_thinker) 9 | camera.conf(cc.PIXFORMAT,cc.PIXFORMAT_RGB565) # both pixformat and 10 | camera.conf(cc.FRAMESIZE,cc.FRAMESIZE_QQVGA) # framesize MUST before camera.init 11 | camera.init() 12 | 13 | # other setting after init 14 | camera.quality(12) 15 | spi = SPI(1, baudrate=60000000, polarity=0, phase=0) 16 | tft=TFT(spi,2,15,12) 17 | tft.init_7735(tft.GREENTAB80x160) 18 | tft.fill(TFT.BLACK) 19 | def display(): 20 | w,h=160-1,80-1 21 | s0=160*20*2 22 | sx=160*100*2 23 | loc=tft._setwindowloc 24 | take=camera.capture 25 | put=tft._writedata 26 | while True: 27 | img=take() 28 | loc((0,0),(w,h)) 29 | put(img[s0:sx]) 30 | 31 | try: 32 | display() 33 | except: 34 | sleep(1) 35 | print('System reseting...') 36 | reset() 37 | 38 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32/AI-Thinker-OV2640/WiFi-SSL/README.md: -------------------------------------------------------------------------------- 1 | 2 | # WiFi w/SSL 3 | ``` 4 | $ strings firmware.bin | grep IDF 5 | MicroPython-1.20.0-xtensa-IDFv4.4.5-with-newlib3.3.0 6 | 7 | $ strings firmware.bin | grep KAKI5 8 | ; ESP32 CAMERA w/SSL (KAKI5) with ESP32 9 | ``` 10 | 11 | The firmware has the AI-Thinker Camera pin configuration by default. A simple streaming server running on the camera board and an openCV client running on a Linux machine are provided as examples. 12 | 13 | # Server 14 | ``` 15 | $ tio /dev/ttyUSB0 16 | 17 | >>> 18 | MPY: soft reboot 19 | MicroPython v1.20.0-206-g33b403dfb-kaki5 on 2023-07-11; ESP32 CAMERA w/SSL (KAKI5) with ESP32 20 | >>> import streaming_server 21 | Camera ready?: True 22 | Waiting ... 23 | Waiting ... 24 | Connected to dlink-3530 25 | network config: ('192.168.4.48', '255.255.252.0', '192.168.4.1', '192.168.4.1') 26 | Request from: ('192.168.4.27', 38962) 27 | TCP send error [Errno 104] ECONNRESET 28 | 29 | ``` 30 | # Client 31 | 32 | ``` 33 | $ python streaming_client.py 34 | Video stop 35 | 36 | ``` 37 | -------------------------------------------------------------------------------- /X23/esp32-aiThinker/tests/test_gray.py: -------------------------------------------------------------------------------- 1 | from st7735f import TFT,TFTColor 2 | from machine import SPI,Pin,reset 3 | from time import sleep 4 | import camera 5 | import cam_config as cc 6 | 7 | # set camera configuration 8 | cc.configure(camera, cc.ai_thinker) 9 | camera.conf(cc.PIXFORMAT,cc.PIXFORMAT_RGB565) # both pixformat and 10 | camera.conf(cc.FRAMESIZE,cc.FRAMESIZE_QQVGA) # framesize MUST before camera.init 11 | camera.init() 12 | 13 | # other setting after init 14 | camera.quality(12) 15 | camera.speffect(2) # black and white 16 | spi = SPI(1, baudrate=60000000, polarity=0, phase=0) 17 | tft=TFT(spi,2,15,12) 18 | tft.init_7735(tft.GREENTAB80x160) 19 | tft.fill(TFT.BLACK) 20 | def display(): 21 | w,h=160-1,80-1 22 | s0=160*20*2 23 | sx=160*100*2 24 | loc=tft._setwindowloc 25 | take=camera.capture 26 | put=tft._writedata 27 | while True: 28 | img=take() 29 | loc((0,0),(w,h)) 30 | put(img[s0:sx]) 31 | 32 | try: 33 | display() 34 | except: 35 | sleep(1) 36 | print('System reseting...') 37 | reset() 38 | 39 | -------------------------------------------------------------------------------- /firmwares-20230521/BTC/README.md: -------------------------------------------------------------------------------- 1 | Firmware with Bluetooth Classic, not included BLE and WiFI. 2 | 3 | ``` 4 | MicroPython v1.20.0-39-g61b8e1b2d-kaki5 on 2023-05-23; ESP32 CAMERA Bluetooth Classic (KAKI5) module with ESP32 5 | >>> dir() 6 | ['uos', 'gc', '__name__', 'bdev'] 7 | >>> gc.mem_free() 8 | 2175168 9 | >>> import bts 10 | >>> bts. 11 | close __dict__ data deinit 12 | get_bin get_str init ready 13 | send_bin send_str up 14 | >>> gc.mem_free() 15 | 2174848 16 | >>> bts.init("SLV-1", "2761") 17 | True 18 | >>> bts.up() 19 | True 20 | >>> import camera 21 | >>> camera.init() 22 | E (448640) gpio: gpio_install_isr_service(449): GPIO isr service already installed 23 | True 24 | >>> bts.data() 25 | 5 26 | >>> w=bts.get_str(100) 27 | >>> w 28 | 'hello' 29 | >>> bts.ready() 30 | True 31 | >>> bts.send_bin(b'ok') 32 | >>> img=camera.capture() 33 | >>> gc.mem_free() 34 | 2121040 35 | 36 | ``` 37 | 38 | More information about Bluetooth Classic module can be founnd [here](https://github.com/shariltumin/esp32-bluetooth-classic-micropython). 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Sharil Tumin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /firmware-20221203/README.md: -------------------------------------------------------------------------------- 1 | 2 | MicroPython v1.19.1-705-gac5934c96-kaki5 on 2022-12-03; ESP32 CAMERA w/SSL 3 | 4 | This firmware has the support of SSL. It is experiential. It has not been properly tested for sending a JPEG image to a proper server over SSL. 5 | 6 | The following test script simply checks whether we have enough runtime RAM when WIFI, camera, and SSL are loaded. 7 | 8 | ``` 9 | import network 10 | import usocket as _socket 11 | import ussl as ssl 12 | import camera 13 | 14 | camera.init() 15 | 16 | network.WLAN(network.AP_IF).active(False) 17 | wlan = network.WLAN(network.STA_IF) 18 | wlan.active(True) 19 | wlan.connect("your SSID", "your PWD") 20 | 21 | img=camera.capture() 22 | 23 | s = _socket.socket() 24 | ai = _socket.getaddrinfo("micropython.org", 443) 25 | addr = ai[0][-1] 26 | print("Connect address:", addr) 27 | s.connect(addr) 28 | s = ssl.wrap_socket(s) 29 | s.write(b"GET / HTTP/1.0\r\n\r\n") 30 | print(s.read(1024)) 31 | 32 | print(len(img)) 33 | ``` 34 | 35 | When everything is working properly, you will receive 1 KB from micropython.org as well as a number representing the length of the image captured earlier in the script. 36 | 37 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/README.md: -------------------------------------------------------------------------------- 1 | 2 | Currently, three ESP32-S3 camera boards are supported. 3 | 4 | 1. LILYGO-T-Camera-OV2640 N16R8 (Flash 16MB, PSRAM 8MB) 5 | 2. XIAO-Sense-OV2640 N8R8 (Flash 8MB, PSRAM 8MB) 6 | 3. Freenove-OV2640 N8R8 (Flash 8MB, PSRAM 8MB) 7 | 8 | The process of flashing the ESP32-S3 firmware is a bit different from that of the ESP32. It is possible that your Thonny IDE does not support ESP32-S3. You will have to use esptool.py to flash the firmware. 9 | 10 | ``` 11 | esptool.py --port /dev/ttyACM0 \ 12 | --baud 460800 --before default_reset --after hard_reset \ 13 | --chip esp32s3 write_flash --flash_mode dio --flash_size detect \ 14 | --flash_freq 80m 0x0 firmware.bin 15 | 16 | ``` 17 | 18 | The LILYGO-T-camera board is a bit special. The OV2640 camera sensor gets its power from the AXP2101 PMU (Power Management Unit). This PMU must be set properly to power the OV2640. The firmware for the LILYGO-T camera has two extra frozen modules, I2CInterface.py and AXP2101.py, to help accomplish this task. I used the work of [Lewis](https://github.com/lewisxhe/XPowersLib/tree/master), thanks! You may also want to take a look at [this](https://github.com/Xinyuan-LilyGO/LilyGo-Cam-ESP32S3/tree/master). 19 | 20 | 21 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/XIAO-Sense-OV2640/scripts/License.txt: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | # 3 | # Copyright (c) Sharil Tumin 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/LILYGO-T-Camera-OV2640/scripts/License.txt: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | # 3 | # Copyright (c) Sharil Tumin 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /X23/esp32s3-freenove/notes/README.md: -------------------------------------------------------------------------------- 1 | 2 | On-board SD Card reader 3 | 4 | ```py 5 | >>> from machine import SDCard 6 | >>> sd = SDCard(slot=1, cd=None, wp=None) 7 | >>> sd.info() 8 | (1006632960, 512) 9 | >>> os.mount(sd, '/sd') 10 | >>> import camera 11 | >>> camera.init() 12 | True 13 | >>> img = camera.capture() 14 | >>> len(img) 15 | 13288 16 | >>> with open('/sd/img1.jpg', 'wb') as f: 17 | ... f.write(img) 18 | ... 19 | 13288 20 | >>> os.listdir('/sd') 21 | ['img1.jpg'] 22 | >>> os.umount('/sd') 23 | >>> camera.deinit() 24 | True 25 | >>> 26 | MPY: soft reboot 27 | 28 | ``` 29 | 30 | We have http-based streaming server 31 | 32 | ```py 33 | >>> 34 | >>> import streaming_server 35 | Camera ready?: True 36 | WIFI not ready. Wait... 37 | WIFI not ready. Wait... 38 | WIFI ready 39 | ('192.168.4.74', '255.255.252.0', '192.168.4.1', '192.168.4.1') 40 | Request from: ('192.168.4.27', 34080) 41 | TCP send error [Errno 113] ECONNABORTED 42 | Request from: ('192.168.4.27', 36656) 43 | ``` 44 | 45 | Now and then you might get "[Errno 113] ECONNABORTED". I don't know why the esp32s3 board got disconnect from the router. One thing for sure is that power supply and the board placement relative to the WiFi router can play some roles on how stable the the connection is. 46 | 47 | 48 | -------------------------------------------------------------------------------- /firmwares-20230717/README.md: -------------------------------------------------------------------------------- 1 | These are the latest firmwares for MicroPython with camera based on esp-idf-445. The firmware version is v1.20.0-206-g33b403dfb. Newer versions of MicroPython will only build on esp-idf-5xx, the esp-idf-4xx versions are no longer supported. 2 | 3 | I will freeze the camera firmware at v1.20.0-206 for now. Newer MicroPython based on esp-idf-502 still have some problems. I will build newer firmwares when these issues are fixed in the future. 4 | 5 | Please refer to the [Note](https://github.com/shariltumin/esp32-cam-micropython-2022/blob/main/firmwares-20230717/Note.md) for information on the use of settings and functions in the camera module. 6 | 7 | Subdirectory [ESP32](https://github.com/shariltumin/esp32-cam-micropython-2022/tree/main/firmwares-20230717/ESP32) contains firmwares for esp32-cam boards and subdirectory [ESP32-S3](https://github.com/shariltumin/esp32-cam-micropython-2022/tree/main/firmwares-20230717/ESP32-S3) contains firmwares for esp32-s3 boards. These firmwares only support the OV2640 sensor. 8 | 9 | The MicroPython core team has now decided to drop the 'u' prefix from all modules. You can now do *import socket* instead of *import usocket as socket*. 10 | 11 | These firmwares are not fully tested, my apologies in advance if they do not work as expected. 12 | -------------------------------------------------------------------------------- /firmwares-20230521/README.md: -------------------------------------------------------------------------------- 1 | Here are 2 firmwares for MicroPython v1.20.0-39. They were compiled with ESP-IDFv4.4.4. 2 | 1. WIFI+TLS (Wifi with SSL, without BLE) 3 | 2. BLE (Bluetooth BLE, without Wifi) 4 | 5 | You decide which one you require for your projects. There is no firmware that supports both WiFi and Bluetooth Low Energy. 6 | 7 | The camera module now has an additional method camera.conf(). You can use it to set the camera configuration, such as PINs, camera CLOCK, format and framesize. This should be done before calling camera.init(). See the scripts/config.pyconfig.py file for details. How to use it 8 | 9 | ```python 10 | import camera 11 | import config as K 12 | 13 | camera.conf(K.XCLK_MHZ, 14) # 14Mhz xclk rate 14 | cam = camera.init() 15 | 16 | img = img = camera.capture() 17 | 18 | ``` 19 | 20 | The firmwares have been compiled with the AI-Thinker esp32-cam board as default configuration. They only support the OV2640. If you have a different configuration, it is possible to define a custom configuration in the config.py, for example wrover_test. To set up your camera, just follow this code sequence 21 | 22 | ```python 23 | import camera 24 | import config as K 25 | 26 | K.configure(camera, K.wrover_test) 27 | cam = camera.init() 28 | 29 | img = img = camera.capture() 30 | 31 | ``` 32 | 33 | I am working on firmwares for esp32-wrover, esp32-s2, esp32-s3 with OV7670, OV2640 and OV5640. The camera.conf() and config.py is a step in that direction. 34 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/XIAO-Sense-OV2640/README.md: -------------------------------------------------------------------------------- 1 | 2 | # WiFi 3 | 4 | This firmware supports WiFi with Socket/SSl, no BLE. 5 | 6 | ``` 7 | $ strings firmware.bin | grep IDF 8 | MicroPython-1.20.0-xtensa-IDFv4.4.5-with-newlib3.3.0 9 | 10 | $ strings firmware.bin | grep OV2640 11 | ; ESP32S3-XIAO OV2640 (KAKI5) with ESP32-S3 12 | 13 | ``` 14 | 15 | # WiFi+BLE 16 | 17 | This firmware supports WiFi with Socket/SSl and BLE. 18 | 19 | ``` 20 | $ strings firmware.bin | grep IDF 21 | MicroPython-1.20.0-xtensa-IDFv4.4.5-with-newlib3.3.0 22 | 23 | $ strings firmware.bin | grep OV2640 24 | ; ESP32S3-XIAO OV2640 w/BLE (KAKI5) with ESP32-S3 25 | 26 | ``` 27 | 28 | -------------------------------------------------------- 29 | 30 | The firmware has the XIAO Sense Camera pin configuration by default. A simple streaming server running on the camera board and an openCV client running on a Linux machine are provided as examples. 31 | 32 | # Server 33 | ``` 34 | >>> 35 | MPY: soft reboot 36 | MicroPython v1.20.0-206-g33b403dfb-kaki5 on 2023-07-10; ESP32S3-XIAO OV2640 w/BLE (KAKI5) with ESP32-S3 37 | >>> import streaming_server 38 | Camera ready?: True 39 | Waiting ... 40 | Waiting ... 41 | Connected to dlink-3530 42 | network config: ('192.168.4.70', '255.255.252.0', '192.168.4.1', '192.168.4.1') 43 | Request from: ('192.168.4.27', 39946) 44 | TCP send error [Errno 104] ECONNRESET 45 | 46 | ``` 47 | 48 | # Client 49 | ``` 50 | $ python streaming_client.py 51 | Video stop 52 | 53 | ``` 54 | 55 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/Freenove-OV2640/README.md: -------------------------------------------------------------------------------- 1 | 2 | # WiFi 3 | 4 | This firmware supports WiFi with Socket/SSl, no BLE. 5 | 6 | ``` 7 | $ strings firmware.bin | grep IDF 8 | MicroPython-1.20.0-xtensa-IDFv4.4.5-with-newlib3.3.0 9 | 10 | $ strings firmware.bin | grep OV2640 11 | ; ESP32S3-FREENOVE OV2640 (KAKI5) with ESP32-S3 12 | 13 | ``` 14 | 15 | # WiFi+BLE 16 | 17 | This firmware supports WiFi with Socket/SSl and BLE. 18 | 19 | ``` 20 | $ strings firmware.bin | grep IDF 21 | MicroPython-1.20.0-xtensa-IDFv4.4.5-with-newlib3.3.0 22 | 23 | $ strings firmware.bin | grep OV2640 24 | ; ESP32S3-FREENOVE OV2640 w/BLE (KAKI5) with ESP32-S3 25 | ``` 26 | 27 | -------------------------------------------------------- 28 | 29 | The firmware has the FREENOVE ESP32-S3-WROOM Camera pin configuration by default. A simple streaming server running on the camera board and an openCV client running on a Linux machine are provided as examples. 30 | 31 | REPL is on the USB-OTG connector. 32 | 33 | # Server 34 | ``` 35 | >>> 36 | MPY: soft reboot 37 | MicroPython v1.20.0-206-g33b403dfb-kaki5 on 2023-07-10; ESP32S3-FREENOVE OV2640 w/BLE (KAKI5) with ESP32-S3 38 | >>> import streaming_server 39 | Camera ready?: True 40 | Waiting ... 41 | Waiting ... 42 | Connected to dlink-3530 43 | network config: ('192.168.4.74', '255.255.252.0', '192.168.4.1', '192.168.4.1') 44 | Request from: ('192.168.4.27', 44764) 45 | TCP send error [Errno 104] ECONNRESET 46 | 47 | ``` 48 | 49 | # Client 50 | ``` 51 | $ python streaming_client.py 52 | Video stop 53 | 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /firmwares-20230521/BLE/README.md: -------------------------------------------------------------------------------- 1 | Firmware with BLE only, without WiFi 2 | 3 | ``` 4 | MicroPython v1.20.0-39-g61b8e1b2d-kaki5 on 2023-05-20; ESP32 CAMERA BLE (KAKI5) module with ESP32 5 | >>> import camera 6 | >>> import bluetooth 7 | >>> bluetooth. 8 | BLE FLAG_INDICATE FLAG_NOTIFY FLAG_READ 9 | FLAG_WRITE FLAG_WRITE_NO_RESPONSE UUID 10 | >>> ble = bluetooth.BLE() 11 | >>> ble. 12 | active config gap_advertise gap_connect 13 | gap_disconnect gap_pair gap_passkey gap_scan 14 | gattc_discover_characteristics gattc_discover_descriptors 15 | gattc_discover_services gattc_exchange_mtu 16 | gattc_read gattc_write gatts_indicate gatts_notify 17 | gatts_read gatts_register_services gatts_set_buffer 18 | gatts_write irq 19 | >>> camera. 20 | aecvalue aelevels agcgain brightness 21 | capture conf contrast deinit 22 | flip framesize init mirror 23 | pixformat quality saturation speffect 24 | whitebalance 25 | >>> camera.init() 26 | E (33556) gpio: gpio_install_isr_service(449): GPIO isr service already installed 27 | True 28 | >>> img=camera.capture() 29 | >>> len(img) 30 | 13634 31 | >>> camera.framesize(11) 32 | >>> img=camera.capture() 33 | >>> len(img) 34 | 18141 35 | >>> camera.framesize(13) 36 | >>> img = camera.capture() 37 | >>> img = camera.capture() 38 | E (184114) camera: Camera Capture Failed 39 | >>> img = camera.capture() 40 | E (192574) camera: Camera Capture Failed 41 | ``` 42 | 43 | I am interested to know how you are using camera module with BLE. Please share your projects. 44 | -------------------------------------------------------------------------------- /firmwares-20230521/BLE/example/ble_cam.py: -------------------------------------------------------------------------------- 1 | 2 | import camera, machine, uos 3 | from esp32_ble import BLE 4 | import time 5 | 6 | # init camera 7 | cam = camera.init() 8 | if cam: 9 | print("Camera ready?: ", cam) 10 | else: 11 | camera.deinit() 12 | machine.reset() # just reset 13 | 14 | # set preffered camera setting 15 | camera.framesize(10) # frame size 800X600 (1.33 espect ratio) 16 | camera.contrast(2) # increase contrast 17 | camera.speffect(2) # jpeg grayscale 18 | img=camera.capture() # throw away 1.st frame 19 | 20 | # init ble 21 | ble = BLE("ESP32-KAKI5") 22 | 23 | # mount sdcard 24 | sd=machine.SDCard(slot=1) 25 | uos.mount(sd, "/sd") 26 | 27 | max_frames = 500 # max(whatever you want) limit 9999 & card capacity 28 | cnt = 0 29 | grab = False 30 | idx = 0 31 | fn = '' 32 | f = None 33 | 34 | while 1: 35 | msg = ble.get_message() 36 | if msg: # not '' 37 | if msg == 'start': # start/resart recoding 38 | grab = True 39 | elif msg == 'stop': # stop recording 40 | grab = False 41 | elif msg == 'bye': 42 | grab = False 43 | break # break out of loop 44 | else: 45 | pass # do nothing 46 | if grab: 47 | fn = '/sd/pic-%04d.jpg'%idx # max: pic-9999.jpg 48 | f = open(fn, 'wb') 49 | img=camera.capture() 50 | if len(img) > 0 and f: 51 | f.write(img) 52 | print('Frame:', idx) 53 | idx += 1 54 | f.close() 55 | f = None 56 | if idx>max_frames: # guard 57 | grab = False 58 | break # breakout limit reached 59 | else: 60 | #time.sleep_ms(30) # every 30 ms 61 | pass # as fast as possible 62 | if f: 63 | f.close() 64 | 65 | uos.listdir("/sd") 66 | uos.umount("/sd") 67 | camera.deinit() 68 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/LILYGO-T-Camera-OV2640/README.md: -------------------------------------------------------------------------------- 1 | 2 | # WiFi 3 | 4 | This firmware supports WiFi with Socket/SSl, no BLE. 5 | 6 | ``` 7 | $ strings firmware.bin | grep IDF 8 | MicroPython-1.20.0-xtensa-IDFv4.4.5-with-newlib3.3.0 9 | 10 | $ strings firmware.bin | grep OV2640 11 | ; ESP32S3-LILYGO T-Cam OV2640 (KAKI5) with ESP32-S3 12 | 13 | ``` 14 | 15 | # WiFi+BLE 16 | 17 | This firmware supports WiFi with Socket/SSl and BLE. 18 | 19 | ``` 20 | $ strings firmware.bin | grep IDF 21 | MicroPython-1.20.0-xtensa-IDFv4.4.5-with-newlib3.3.0 22 | 23 | $ strings firmware.bin | grep OV2640 24 | ; ESP32S3-LILYGO T-Cam OV2640 w/BLE (KAKI5) with ESP32-S3 25 | 26 | ``` 27 | 28 | -------------------------------------------------------- 29 | 30 | Lilygo T-Camera needs PMU to work! 31 | 32 | The project uses the work of Lewis He (lewishe@outlook.com) from: 33 | 34 | https://github.com/lewisxhe/XPowersLib/tree/master 35 | 36 | and the example from: 37 | 38 | https://github.com/Xinyuan-LilyGO/LilyGo-Cam-ESP32S3/tree/master 39 | 40 | The firmware has the Lilygo T-Camera pin configuration by default. A simple streaming server running on the camera board and an openCV client running on a Linux machine are provided as examples. 41 | 42 | # Server 43 | ``` 44 | >>> 45 | MPY: soft reboot 46 | MicroPython v1.20.0-206-g33b403dfb-kaki5 on 2023-07-13; ESP32S3-LILYGO T-Cam OV2640 w/BLE (KAKI5) with ESP32-S3 47 | >>> import streaming_server 48 | micropython 49 | AXP2101 __init__ 50 | getID:0x4a 51 | Camera ready?: True 52 | Waiting ... 53 | Waiting ... 54 | Connected to dlink-3530 55 | network config: ('192.168.4.71', '255.255.252.0', '192.168.4.1', '192.168.4.1') 56 | Request from: ('192.168.4.27', 50740) 57 | TCP send error [Errno 104] ECONNRESET 58 | 59 | ``` 60 | 61 | # Client 62 | ``` 63 | $ python streaming_client.py 64 | Video stop 65 | 66 | ``` 67 | 68 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32/AI-Thinker-OV2640/scripts/streaming_client.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # run this on Linux PC with opencv-python module 26 | 27 | import cv2 28 | 29 | dropped = 0 # drop frames count 30 | 31 | # Change to your board IP 32 | vid = cv2.VideoCapture('http://192.168.4.48/ali/Baba40Robrs') # open webcam capture 33 | 34 | while True: 35 | ret, frame = vid.read() # get frame-by-frame 36 | #print(vid.isOpened(), ret) 37 | if frame is not None: 38 | if dropped > 0: dropped = 0 # reset 39 | cv2.imshow('Video-44',frame) # display frame 40 | if cv2.waitKey(22) & 0xFF == ord('q'): # press q to quit 41 | break 42 | else: 43 | dropped += 1 44 | if dropped > 100: 45 | print("Server is down") 46 | break 47 | 48 | # Done, clear all resources 49 | vid.release() 50 | cv2.destroyAllWindows() 51 | print("Video stop") 52 | 53 | 54 | -------------------------------------------------------------------------------- /X23/opencv_scripts/client.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # run this on Linux PC with opencv-python module 26 | 27 | import cv2 28 | 29 | dropped = 0 # drop frames count 30 | 31 | # 192.168.4.44 - AIT esp32s 32 | # Change this to your board IP 33 | # http-based streaming not RTSP 34 | vid = cv2.VideoCapture('http://192.168.4.97/ait/Hi-AIT-123') # open webcam capture 35 | 36 | while True: 37 | ret, frame = vid.read() # get frame-by-frame 38 | #print(vid.isOpened(), ret) 39 | if frame is not None: 40 | if dropped > 0: dropped = 0 # reset 41 | cv2.imshow('Video-44',frame) # display frame 42 | if cv2.waitKey(22) & 0xFF == ord('q'): # press q to quit 43 | break 44 | else: 45 | dropped += 1 46 | if dropped > 100: 47 | print("Server is down") 48 | break 49 | 50 | # Done, clear all resources 51 | vid.release() 52 | cv2.destroyAllWindows() 53 | print("Video stop") 54 | 55 | 56 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/XIAO-Sense-OV2640/scripts/streaming_client.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # run this on Linux PC with opencv-python module 26 | 27 | import cv2 28 | 29 | dropped = 0 # drop frames count 30 | 31 | # 192.168.4.70 - XIAO esp32s3 32 | # Change this to your board IP 33 | vid = cv2.VideoCapture('http://192.168.4.70/xiao/Hi-Xiao-Ling') # open webcam capture 34 | 35 | while True: 36 | ret, frame = vid.read() # get frame-by-frame 37 | #print(vid.isOpened(), ret) 38 | if frame is not None: 39 | if dropped > 0: dropped = 0 # reset 40 | cv2.imshow('Video-44',frame) # display frame 41 | if cv2.waitKey(22) & 0xFF == ord('q'): # press q to quit 42 | break 43 | else: 44 | dropped += 1 45 | if dropped > 100: 46 | print("Server is down") 47 | break 48 | 49 | # Done, clear all resources 50 | vid.release() 51 | cv2.destroyAllWindows() 52 | print("Video stop") 53 | 54 | 55 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/LILYGO-T-Camera-OV2640/scripts/streaming_client.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # run this on Linux PC with opencv-python module 26 | 27 | import cv2 28 | 29 | dropped = 0 # drop frames count 30 | 31 | 32 | # 192.168.4.70 - Lilygo T-camera esp32s3 33 | # change this to your board IP 34 | vid = cv2.VideoCapture('http://192.168.4.71/lily/Hi-Lily-Goen') # open webcam capture 35 | 36 | while True: 37 | ret, frame = vid.read() # get frame-by-frame 38 | #print(vid.isOpened(), ret) 39 | if frame is not None: 40 | if dropped > 0: dropped = 0 # reset 41 | cv2.imshow('Video-44',frame) # display frame 42 | if cv2.waitKey(22) & 0xFF == ord('q'): # press q to quit 43 | break 44 | else: 45 | dropped += 1 46 | if dropped > 100: 47 | print("Server is down") 48 | break 49 | 50 | # Done, clear all resources 51 | vid.release() 52 | cv2.destroyAllWindows() 53 | print("Video stop") 54 | 55 | 56 | -------------------------------------------------------------------------------- /X23/README.md: -------------------------------------------------------------------------------- 1 | 2 | Exit 2023, enter 2024. New year, new opportunity. This work is a revision of the Christmas-2023-Edition and completes the task of providing firmwares for esp32s3 as well. 3 | 4 | Supported firmwares are: 5 | 1. esp32-aiThinker 6 | 2. esp32s3-freenove 7 | 3. esp32s3-lilygo 8 | 4. esp32s3-xiao 9 | 10 | All are compiled with esp-idf-4.4.6 and the camera modules are based on the latest esp32 camera component. 11 | 12 | All firmware includes these frozen display modules: 13 | 1. ssd1306f - OLED Display Module 12864 128x64 Pixel SSD1306. 14 | 2. st7735f - TFT Display 1.8″ 128×160 Pixels ST7735. 15 | 16 | The 'f' suffix is to distinguish the frozen modules from the normal flash based modules, should you wish to use one. 17 | 18 | I've tested the st7735f with esp32-aiThinker and the ssd1306f with esp32s3-lilygo. All the test scripts are in the "tests" directories of the respective boards. The esp32s3-freenove firmware now includes the esp32s3 sd/mmc sd card driver, which means that the onboard sd card driver is now usable for storing data. 19 | 20 | There is now a new way to configure the camera hardware before the camera is initialised. The PIXFORMAT and FRAMESIZE must be set before ```camera.init()```. If you need to change either or both, you need to run ```camera.deinit()``` first. 21 | 22 | Under each "tests" directory, I include a "config_test.py" file. You can run this script to find out what combinations of PIXFORMAT/FRAMESIZE are supported, and what the image file sizes are if a combination is valid. 23 | 24 | All firmwares come with "scripts" directories that contain the following: 25 | 1. auth.py - the authorization variables 26 | 2. cam_config.py - the configuration definitions and the board configuration 27 | 3. streaming_server.py - a simple HTTP image streaming server 28 | 29 | The esp32s3-lilygo needs an extra file, "pmu.py", the power management script. 30 | 31 | Besides providing TFT and OLED display capabilities, I also include some opencv scripts. 32 | 1. client.py 33 | 2. face_detection.py 34 | 3. hands_detection.py 35 | 36 | These scripts are clients of "streaming_server.py". You need to run the opencv scripts on a unix-based PC, and you need Python with opencv-python, czone and all dependencies installed on that PC. 37 | 38 | Good luck with your ESP camera projects for 2024. 39 | 40 | -------------------------------------------------------------------------------- /Christmas-2023-Edition/README.md: -------------------------------------------------------------------------------- 1 | 2 | It is Christmas 2023. Since everyone is on holiday and has time on their hands, why not make the most of it? Ok, I have a present for you all. 3 | 4 | I have made new esp32 camera firmwares with bug fixes of the old ones. With the new firmwares you can set PIXFORMAT correctly to RGB565, a 2bytes/pixel image format. The 2Bytes with 5bits for red, 6bits for green and 5bits for blue can be used directly on TFT (Thin Film Transistor Liquid Crystal) displays such as ST7735, and ST7789. There is no need for a conversion program, just capture an image and send it directly to the display. 5 | 6 | The old firmwares work for JPEG, but setting to a different PIXFORMAT either results in an error or the camera sensor retains the previous JPEG format. The esp-camera ESP-IDF component used in these firmwares behaves differently to the one used before. PIXFORMAT and FRAMESIZE must be set before camera.init(). If you want to change either PIXFORMAT or FRAMESIZE after the camera has been initialised, you must call camera.deinit() first. Any changes will take effect on the next camera.init(). 7 | 8 | The camera.init() and camera.deinit() will return True if everything went fine. Something is wrong if you get False. The only way to fix this is a hard reset(off/on) or machine.reset(). 9 | 10 | The camera.init() in the new firmwares will not set any defaults as before, you will need to configure the camera sensor board using the cam_config MicroPython module, for example: 11 | 12 | ```py 13 | import camera 14 | import cam_config as cc 15 | # set camera configuration 16 | cc.configure(camera, cc.ai_thinker) 17 | camera.init() 18 | ``` 19 | 20 | The cc.ai_thinker is a dict that contains all the pins and default configuration settings. This provides flexibility. Users can adjust the settings according to their OV2640 boards. For example, if you are using the external "Red Board" and you are using the settings in "cam_config.py", you can just do ```cc.configure(camera, cc.red_board)```. 21 | 22 | These firmwares only support the OV2640 camera sensor. By using "cam_config.py" it is possible to use any OV2640 board. You will need to set the pins correctly. 23 | 24 | I have tested the esp32-cam (ai-thinker) board and ST7735. I got good results. You can find the test codes in the scripts directory. 25 | 26 | Best of luck and Happy New Year, 2024. 27 | 28 | 29 | -------------------------------------------------------------------------------- /firmwares-20230521/BLE/example/README.md: -------------------------------------------------------------------------------- 1 | 2 | The script esp32_ble.py implements the BLE class for the Nordic UART service on the ESP32-cam. 3 | 4 | Thanks to the original contributor(s) whose name I do not know. 5 | 6 | There are a few changes. For event type 3, the oldest message is kept. The current message is dropped if the message slot is not empty. The method get_message() returns the current message and clears the slot. The assumption here is that get_message() is called in a tight loop, much more often than a client sends a message. 7 | 8 | You can send text messages to it using Serial Bluetooth Terminal app on an Android phone. I have problems connecting from an old Android 5.1 phone. No problem from a newer phone with Android 10. 9 | 10 | The ble_cam.py script is a sample script that uses the esp32_ble.py module. The script will announce its name and ESP32-KAKI5 will be shown as a BLE device that a client can connect to. 11 | 12 | Once connected, image (jpg) recording begins, one frame per file, with a 'start' message. A 'stop' message pauses recording until another 'start' message is sent, which resumes recording. A 'bye' message exits the main loop. The program returns to REPL. 13 | 14 | There is a guard variable, max_frames, which sets an upper limit on the number of frames to capture. 15 | 16 | For autostart, you can add this line to your main.py 17 | ``` 18 | import ble_cam 19 | ``` 20 | 21 | When you are done capturing images, transfer the SD card to a Linux PC. Do the following to convert the image files to mp4 video. 22 | 23 | ``` 24 | $ df | grep 'media' 25 | /dev/sda1 7708672 18336 7690336 1% /media/sharil/0E0B-1721 26 | 27 | $ ffmpeg -framerate 4 -i /media/sharil/0E0B-1721/pic-%04d.jpg video.mp4 28 | 29 | $ celluloid video.mp4 30 | 31 | ``` 32 | 33 | Use ffmpeg to convert jpg files into an mp4 file. Use celluloid to view the final video file. 34 | 35 | Sorry, I have no tips if you are on Windows or Mac. Maybe you can convert of your old Windows laptop into a Linux PC? 36 | 37 | Images out from the camera sensor are in jpeg format. There no support for avi or mp4 format. It is tempting to capture images and save all into a single file, for example video.avi, will will not work, as far as I know. 38 | 39 | By the way, you can put a 5 minute sleep in the while loop. Turn off your BLE client, you will still be capturing frames, now every 5 minutes. 40 | 41 | Later, you can reconnect and send stop and bye. 42 | -------------------------------------------------------------------------------- /X23/esp32s3-lilygo/tests/oled_test_1.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | from machine import reset, SoftI2C, Pin 26 | from pmu import cam_power_on 27 | import ssd1306f 28 | import camera 29 | import cam_config as cc 30 | from time import sleep 31 | 32 | # Switch on camera power controlled by AXP2101 33 | cam_power_on() 34 | 35 | # camera 36 | camera.conf(cc.FRAMESIZE, cc.FRAMESIZE_QQVGA) # 160x120 37 | camera.conf(cc.PIXFORMAT, cc.PIXFORMAT_GRAYSCALE) 38 | cam = camera.init() 39 | 40 | if not cam: 41 | print('No camera. Hard reset!!') 42 | sleep(5) 43 | reset() 44 | 45 | # liligo t-camera board 46 | i2c = SoftI2C(Pin(6), Pin(7)) # id, scl, sda 47 | # i2c.scan() # [52, 60] 48 | display = ssd1306f.SSD1306_I2C(128, 64, i2c) 49 | 50 | @micropython.native 51 | def see(dark = 120): # dark threshold value default 120 52 | # display.invert(1) # 1 invert / 0 normal 53 | while True: 54 | img=camera.capture_bmp()[160*10:] # skip 10 row from captured image 55 | for y in range(64): 56 | cnt=160*y 57 | for x in range(128): 58 | display.pixel(x,y,(0 if img[cnt] 0: dropped = 0 # reset 47 | frame, faces = face.findFaces(frame) 48 | # if faces: 49 | # do other face processing 50 | cv2.imshow('Faces',frame) # display frame 51 | if cv2.waitKey(22) & 0xFF == ord('q'): # press q to quit 52 | break 53 | else: 54 | dropped += 1 55 | if dropped > 100: 56 | print("Server is down") 57 | break 58 | 59 | # Done, clear all resources 60 | vid.release() 61 | cv2.destroyAllWindows() 62 | print("Video stop") 63 | 64 | 65 | -------------------------------------------------------------------------------- /wifi.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | #Basic WiFi configuration: 26 | 27 | from time import sleep 28 | import network 29 | import site 30 | 31 | class Sta: 32 | 33 | AP = "YOUR-SSID" 34 | PWD = "YOUR-PWD" 35 | 36 | def __init__(my, ap='', pwd=''): 37 | network.WLAN(network.AP_IF).active(False) # disable access point 38 | my.wlan = network.WLAN(network.STA_IF) 39 | my.wlan.active(True) 40 | if ap == '': 41 | my.ap = Sta.AP 42 | my.pwd = Sta.PWD 43 | else: 44 | my.ap = ap 45 | my.pwd = pwd 46 | 47 | def connect(my, ap='', pwd=''): 48 | if ap != '': 49 | my.ap = ap 50 | my.pwd = pwd 51 | 52 | if not my.wlan.isconnected(): 53 | my.wlan.connect(my.ap, my.pwd) 54 | 55 | def status(my): 56 | if my.wlan.isconnected(): 57 | return my.wlan.ifconfig() 58 | else: 59 | return () 60 | 61 | def wait(my): 62 | cnt = 30 63 | while cnt > 0: 64 | print("Waiting ..." ) 65 | # con(my.ap, my.pwd) # Connect to an AP 66 | if my.wlan.isconnected(): 67 | print("Connected to %s" % my.ap) 68 | print('network config:', my.wlan.ifconfig()) 69 | site.server=my.wlan.ifconfig()[0] 70 | cnt = 0 71 | else: 72 | sleep(5) 73 | cnt -= 5 74 | return 75 | 76 | def scan(my): 77 | return my.wlan.scan() # Scan for available access points 78 | 79 | -------------------------------------------------------------------------------- /X23/esp32s3-lilygo/tests/oled_test.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | from machine import reset, SoftI2C, Pin 26 | from pmu import cam_power_on 27 | import ssd1306f 28 | import camera 29 | import cam_config as cc 30 | from time import sleep 31 | 32 | # Switch on camera power controlled by AXP2101 33 | cam_power_on() 34 | 35 | # camera 36 | camera.conf(cc.FRAMESIZE, cc.FRAMESIZE_QQVGA) # 160x120 37 | camera.conf(cc.PIXFORMAT, cc.PIXFORMAT_GRAYSCALE) 38 | cam = camera.init() 39 | 40 | if not cam: 41 | print('No camera. Hard reset!!') 42 | sleep(5) 43 | reset() 44 | 45 | # liligo t-camera board 46 | i2c = SoftI2C(Pin(6), Pin(7)) # id, scl, sda 47 | # i2c.scan() # [52, 60] 48 | display = ssd1306f.SSD1306_I2C(128, 64, i2c) 49 | 50 | @micropython.native 51 | def see(): # 52 | # display.invert(1) # 1 invert / 0 normal 53 | while True: 54 | img=camera.capture_bmp()[160*10:] # skip 10 rows from image 55 | for dark in (115, 125, 120, 117, 122): # dark threshold values, your choice 56 | # to simulate grayscale 57 | for y in range(64): 58 | cnt=160*y 59 | for x in range(128): 60 | display.pixel(x,y,(0 if img[cnt] 0: 63 | print("Waiting ..." ) 64 | # con(my.ap, my.pwd) # Connect to an AP 65 | if my.wlan.isconnected(): 66 | print("Connected to %s" % my.ap) 67 | print('network config:', my.wlan.ifconfig()) 68 | site.server=my.wlan.ifconfig()[0] 69 | cnt = 0 70 | else: 71 | sleep(5) 72 | cnt -= 5 73 | return 74 | 75 | def scan(my): 76 | return my.wlan.scan() # Scan for available access points 77 | 78 | 79 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32/AI-Thinker-OV2640/scripts/Wifi.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | #Basic WiFi configuration: 26 | 27 | from time import sleep 28 | import network 29 | 30 | class Sta: 31 | 32 | AP = "dlink-2391" # change to your SSID 33 | PWD = "f34RT114k" # cjange to your password 34 | 35 | def __init__(my, ap='', pwd=''): 36 | network.WLAN(network.AP_IF).active(False) # disable access point 37 | my.wlan = network.WLAN(network.STA_IF) 38 | my.wlan.active(True) 39 | if ap == '': 40 | my.ap = Sta.AP 41 | my.pwd = Sta.PWD 42 | else: 43 | my.ap = ap 44 | my.pwd = pwd 45 | 46 | def connect(my, ap='', pwd=''): 47 | if ap != '': 48 | my.ap = ap 49 | my.pwd = pwd 50 | 51 | if not my.wlan.isconnected(): 52 | my.wlan.connect(my.ap, my.pwd) 53 | 54 | def status(my): 55 | if my.wlan.isconnected(): 56 | return my.wlan.ifconfig() 57 | else: 58 | return () 59 | 60 | def wait(my): 61 | cnt = 30 62 | while cnt > 0: 63 | print("Waiting ..." ) 64 | # con(my.ap, my.pwd) # Connect to an AP 65 | if my.wlan.isconnected(): 66 | print("Connected to %s" % my.ap) 67 | print('network config:', my.wlan.ifconfig()) 68 | cnt = 0 69 | else: 70 | sleep(5) 71 | cnt -= 5 72 | return 73 | 74 | def scan(my): 75 | return my.wlan.scan() # Scan for available access points 76 | 77 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/XIAO-Sense-OV2640/scripts/Wifi.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | #Basic WiFi configuration: 26 | 27 | from time import sleep 28 | import network 29 | 30 | class Sta: 31 | 32 | AP = "dlink-2391" # change to your SSID 33 | PWD = "f34RT114k" # cjange to your password 34 | 35 | def __init__(my, ap='', pwd=''): 36 | network.WLAN(network.AP_IF).active(False) # disable access point 37 | my.wlan = network.WLAN(network.STA_IF) 38 | my.wlan.active(True) 39 | if ap == '': 40 | my.ap = Sta.AP 41 | my.pwd = Sta.PWD 42 | else: 43 | my.ap = ap 44 | my.pwd = pwd 45 | 46 | def connect(my, ap='', pwd=''): 47 | if ap != '': 48 | my.ap = ap 49 | my.pwd = pwd 50 | 51 | if not my.wlan.isconnected(): 52 | my.wlan.connect(my.ap, my.pwd) 53 | 54 | def status(my): 55 | if my.wlan.isconnected(): 56 | return my.wlan.ifconfig() 57 | else: 58 | return () 59 | 60 | def wait(my): 61 | cnt = 30 62 | while cnt > 0: 63 | print("Waiting ..." ) 64 | # con(my.ap, my.pwd) # Connect to an AP 65 | if my.wlan.isconnected(): 66 | print("Connected to %s" % my.ap) 67 | print('network config:', my.wlan.ifconfig()) 68 | cnt = 0 69 | else: 70 | sleep(5) 71 | cnt -= 5 72 | return 73 | 74 | def scan(my): 75 | return my.wlan.scan() # Scan for available access points 76 | 77 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/LILYGO-T-Camera-OV2640/scripts/Wifi.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | #Basic WiFi configuration: 26 | 27 | from time import sleep 28 | import network 29 | 30 | class Sta: 31 | 32 | AP = "dlink-2391" # change to your SSID 33 | PWD = "f34RT114k" # cjange to your password 34 | 35 | def __init__(my, ap='', pwd=''): 36 | network.WLAN(network.AP_IF).active(False) # disable access point 37 | my.wlan = network.WLAN(network.STA_IF) 38 | my.wlan.active(True) 39 | if ap == '': 40 | my.ap = Sta.AP 41 | my.pwd = Sta.PWD 42 | else: 43 | my.ap = ap 44 | my.pwd = pwd 45 | 46 | def connect(my, ap='', pwd=''): 47 | if ap != '': 48 | my.ap = ap 49 | my.pwd = pwd 50 | 51 | if not my.wlan.isconnected(): 52 | my.wlan.connect(my.ap, my.pwd) 53 | 54 | def status(my): 55 | if my.wlan.isconnected(): 56 | return my.wlan.ifconfig() 57 | else: 58 | return () 59 | 60 | def wait(my): 61 | cnt = 30 62 | while cnt > 0: 63 | print("Waiting ..." ) 64 | # con(my.ap, my.pwd) # Connect to an AP 65 | if my.wlan.isconnected(): 66 | print("Connected to %s" % my.ap) 67 | print('network config:', my.wlan.ifconfig()) 68 | cnt = 0 69 | else: 70 | sleep(5) 71 | cnt -= 5 72 | return 73 | 74 | def scan(my): 75 | return my.wlan.scan() # Scan for available access points 76 | 77 | -------------------------------------------------------------------------------- /X23/esp32s3-xiao/tests/config_test.py: -------------------------------------------------------------------------------- 1 | 2 | import camera 3 | import time 4 | import gc 5 | 6 | gc.enable() 7 | 8 | pix = const(17) 9 | frame = const(18) 10 | 11 | # PIXEL FORMAT 12 | PIXFORMAT = { 13 | 'RGB565':1, # 2BPP/RGB565 14 | 'YUV422':2, # 2BPP/YUV422 15 | 'YUV420':3, # 1.5BPP/YUV420 16 | 'GRAYSCALE':4, # 1BPP/GRAYSCALE 17 | 'JPEG':5, # JPEG/COMPRESSED 18 | 'RGB888':6, # 3BPP/RGB888 19 | 'RAW':7, # RAW 20 | 'RGB444':8, # 3BP2P/RGB444 21 | 'RGB555':9, # 3BP2P/RGB555 22 | } 23 | 24 | # FRAME SIZE 25 | FRAMESIZE = { 26 | '96X96':1, # 96x96 27 | 'QQVGA':2, # 160x120 28 | 'QCIF':3, # 176x144 29 | 'HQVGA':4, # 240x176 30 | '240X240':5,# 240x240 31 | 'QVGA':6, # 320x240 32 | 'CIF':7, # 400x296 33 | 'HVGA':8, # 480x320 34 | 'VGA':9, # 640x480 35 | 'SVGA':10, # 800x600 36 | 'XGA':11, # 1024x768 37 | 'HD':12, # 1280x720 38 | 'SXGA':13, # 1280x1024 39 | 'UXGA':14, # 1600x1200 40 | 'FHD':15, # 1920x1080 41 | 'P_HD':16, # 720x1280 42 | 'P_3MP':17, # 864x1536 43 | 'QXGA':18, # 2048x1536 44 | } 45 | 46 | camera.init() 47 | 48 | for p in ( 49 | 'RGB565', # 2BPP/RGB565 50 | 'YUV422', # 2BPP/YUV422 51 | 'YUV420', # 1.5BPP/YUV420 52 | 'GRAYSCALE', # 1BPP/GRAYSCALE 53 | 'JPEG', # JPEG/COMPRESSED 54 | 'RGB888', # 3BPP/RGB888 55 | 'RAW', # RAW 56 | 'RGB444', # 3BP2P/RGB444 57 | 'RGB555'): # 3BP2P/RGB555 58 | n = PIXFORMAT.get(p) 59 | for f in ( 60 | '96X96', # 96x96 61 | 'QQVGA', # 160x120 62 | 'QCIF', # 176x144 63 | 'HQVGA', # 240x176 64 | '240X240',# 240x240 65 | 'QVGA', # 320x240 66 | 'CIF', # 400x296 67 | 'HVGA', # 480x320 68 | 'VGA', # 640x480 69 | 'SVGA', # 800x600 70 | 'XGA', # 1024x768 71 | 'HD', # 1280x720 72 | 'SXGA', # 1280x1024 73 | 'UXGA', # 1600x1200 74 | 'FHD', # 1920x1080 75 | 'P_HD', # 720x1280 76 | 'P_3MP', # 864x1536 77 | 'QXGA'): # 2048x1536 78 | s = FRAMESIZE.get(f) 79 | camera.deinit() 80 | time.sleep(1) 81 | gc.collect() 82 | print('Set', p, f, ':') 83 | camera.conf(pix, n) # set pixelformat 84 | camera.conf(frame, s)# set framesize 85 | try: 86 | ok = camera.init() 87 | if not ok: 88 | print('Camera initialization fail') 89 | break 90 | time.sleep(1) 91 | img = camera.capture() 92 | if img: 93 | print('---> Image size:', len(img)) 94 | else: 95 | print('No image captured') 96 | except Exception as e: 97 | print('ERR:', e) 98 | -------------------------------------------------------------------------------- /X23/esp32-aiThinker/tests/config_test.py: -------------------------------------------------------------------------------- 1 | 2 | import camera 3 | import time 4 | import gc 5 | 6 | gc.enable() 7 | 8 | pix = const(17) 9 | frame = const(18) 10 | 11 | # PIXEL FORMAT 12 | PIXFORMAT = { 13 | 'RGB565':1, # 2BPP/RGB565 14 | 'YUV422':2, # 2BPP/YUV422 15 | 'YUV420':3, # 1.5BPP/YUV420 16 | 'GRAYSCALE':4, # 1BPP/GRAYSCALE 17 | 'JPEG':5, # JPEG/COMPRESSED 18 | 'RGB888':6, # 3BPP/RGB888 19 | 'RAW':7, # RAW 20 | 'RGB444':8, # 3BP2P/RGB444 21 | 'RGB555':9, # 3BP2P/RGB555 22 | } 23 | 24 | # FRAME SIZE 25 | FRAMESIZE = { 26 | '96X96':1, # 96x96 27 | 'QQVGA':2, # 160x120 28 | 'QCIF':3, # 176x144 29 | 'HQVGA':4, # 240x176 30 | '240X240':5,# 240x240 31 | 'QVGA':6, # 320x240 32 | 'CIF':7, # 400x296 33 | 'HVGA':8, # 480x320 34 | 'VGA':9, # 640x480 35 | 'SVGA':10, # 800x600 36 | 'XGA':11, # 1024x768 37 | 'HD':12, # 1280x720 38 | 'SXGA':13, # 1280x1024 39 | 'UXGA':14, # 1600x1200 40 | 'FHD':15, # 1920x1080 41 | 'P_HD':16, # 720x1280 42 | 'P_3MP':17, # 864x1536 43 | 'QXGA':18, # 2048x1536 44 | } 45 | 46 | camera.init() 47 | 48 | for p in ( 49 | 'RGB565', # 2BPP/RGB565 50 | 'YUV422', # 2BPP/YUV422 51 | 'YUV420', # 1.5BPP/YUV420 52 | 'GRAYSCALE', # 1BPP/GRAYSCALE 53 | 'JPEG', # JPEG/COMPRESSED 54 | 'RGB888', # 3BPP/RGB888 55 | 'RAW', # RAW 56 | 'RGB444', # 3BP2P/RGB444 57 | 'RGB555'): # 3BP2P/RGB555 58 | n = PIXFORMAT.get(p) 59 | for f in ( 60 | '96X96', # 96x96 61 | 'QQVGA', # 160x120 62 | 'QCIF', # 176x144 63 | 'HQVGA', # 240x176 64 | '240X240',# 240x240 65 | 'QVGA', # 320x240 66 | 'CIF', # 400x296 67 | 'HVGA', # 480x320 68 | 'VGA', # 640x480 69 | 'SVGA', # 800x600 70 | 'XGA', # 1024x768 71 | 'HD', # 1280x720 72 | 'SXGA', # 1280x1024 73 | 'UXGA', # 1600x1200 74 | 'FHD', # 1920x1080 75 | 'P_HD', # 720x1280 76 | 'P_3MP', # 864x1536 77 | 'QXGA'): # 2048x1536 78 | s = FRAMESIZE.get(f) 79 | camera.deinit() 80 | time.sleep(1) 81 | gc.collect() 82 | print('Set', p, f, ':') 83 | camera.conf(pix, n) # set pixelformat 84 | camera.conf(frame, s)# set framesize 85 | try: 86 | ok = camera.init() 87 | if not ok: 88 | print('Camera initialization fail') 89 | break 90 | time.sleep(1) 91 | img = camera.capture() 92 | if img: 93 | print('---> Image size:', len(img)) 94 | else: 95 | print('No image captured') 96 | except Exception as e: 97 | print('ERR:', e) 98 | -------------------------------------------------------------------------------- /X23/esp32s3-freenove/tests/config_test.py: -------------------------------------------------------------------------------- 1 | 2 | import camera 3 | import time 4 | import gc 5 | 6 | gc.enable() 7 | 8 | pix = const(17) 9 | frame = const(18) 10 | 11 | # PIXEL FORMAT 12 | PIXFORMAT = { 13 | 'RGB565':1, # 2BPP/RGB565 14 | 'YUV422':2, # 2BPP/YUV422 15 | 'YUV420':3, # 1.5BPP/YUV420 16 | 'GRAYSCALE':4, # 1BPP/GRAYSCALE 17 | 'JPEG':5, # JPEG/COMPRESSED 18 | 'RGB888':6, # 3BPP/RGB888 19 | 'RAW':7, # RAW 20 | 'RGB444':8, # 3BP2P/RGB444 21 | 'RGB555':9, # 3BP2P/RGB555 22 | } 23 | 24 | # FRAME SIZE 25 | FRAMESIZE = { 26 | '96X96':1, # 96x96 27 | 'QQVGA':2, # 160x120 28 | 'QCIF':3, # 176x144 29 | 'HQVGA':4, # 240x176 30 | '240X240':5,# 240x240 31 | 'QVGA':6, # 320x240 32 | 'CIF':7, # 400x296 33 | 'HVGA':8, # 480x320 34 | 'VGA':9, # 640x480 35 | 'SVGA':10, # 800x600 36 | 'XGA':11, # 1024x768 37 | 'HD':12, # 1280x720 38 | 'SXGA':13, # 1280x1024 39 | 'UXGA':14, # 1600x1200 40 | 'FHD':15, # 1920x1080 41 | 'P_HD':16, # 720x1280 42 | 'P_3MP':17, # 864x1536 43 | 'QXGA':18, # 2048x1536 44 | } 45 | 46 | camera.init() 47 | 48 | for p in ( 49 | 'RGB565', # 2BPP/RGB565 50 | 'YUV422', # 2BPP/YUV422 51 | 'YUV420', # 1.5BPP/YUV420 52 | 'GRAYSCALE', # 1BPP/GRAYSCALE 53 | 'JPEG', # JPEG/COMPRESSED 54 | 'RGB888', # 3BPP/RGB888 55 | 'RAW', # RAW 56 | 'RGB444', # 3BP2P/RGB444 57 | 'RGB555'): # 3BP2P/RGB555 58 | n = PIXFORMAT.get(p) 59 | for f in ( 60 | '96X96', # 96x96 61 | 'QQVGA', # 160x120 62 | 'QCIF', # 176x144 63 | 'HQVGA', # 240x176 64 | '240X240',# 240x240 65 | 'QVGA', # 320x240 66 | 'CIF', # 400x296 67 | 'HVGA', # 480x320 68 | 'VGA', # 640x480 69 | 'SVGA', # 800x600 70 | 'XGA', # 1024x768 71 | 'HD', # 1280x720 72 | 'SXGA', # 1280x1024 73 | 'UXGA', # 1600x1200 74 | 'FHD', # 1920x1080 75 | 'P_HD', # 720x1280 76 | 'P_3MP', # 864x1536 77 | 'QXGA'): # 2048x1536 78 | s = FRAMESIZE.get(f) 79 | camera.deinit() 80 | time.sleep(1) 81 | gc.collect() 82 | print('Set', p, f, ':') 83 | camera.conf(pix, n) # set pixelformat 84 | camera.conf(frame, s)# set framesize 85 | try: 86 | ok = camera.init() 87 | if not ok: 88 | print('Camera initialization fail') 89 | break 90 | time.sleep(1) 91 | img = camera.capture() 92 | if img: 93 | print('---> Image size:', len(img)) 94 | else: 95 | print('No image captured') 96 | except Exception as e: 97 | print('ERR:', e) 98 | -------------------------------------------------------------------------------- /firmwares-20230521/BLE/example/esp32_ble.py: -------------------------------------------------------------------------------- 1 | from machine import Pin, Timer 2 | from time import sleep_ms 3 | import ubluetooth 4 | 5 | class BLE(): 6 | def __init__(self, name): 7 | self.name = name 8 | self.ble = ubluetooth.BLE() 9 | self.ble.active(True) 10 | 11 | self.led = Pin(2, Pin.OUT) 12 | self.timer1 = Timer(0) 13 | self.timer2 = Timer(1) 14 | 15 | self.disconnected() 16 | self.ble.irq(self.ble_irq) 17 | self.register() 18 | self.advertiser() 19 | 20 | self.message = "" 21 | 22 | def connected(self): 23 | self.timer1.deinit() 24 | self.timer2.deinit() 25 | 26 | def disconnected(self): 27 | self.timer1.init(period=1000, mode=Timer.PERIODIC, callback=lambda t: self.led(1)) 28 | sleep_ms(200) 29 | self.timer2.init(period=1000, mode=Timer.PERIODIC, callback=lambda t: self.led(0)) 30 | 31 | def ble_irq(self, event, data): 32 | # print('Event:', event, 'Data:', data) 33 | 34 | if event == 1: 35 | '''Central disconnected''' 36 | self.connected() 37 | self.led(1) 38 | 39 | elif event == 2: 40 | '''Central disconnected''' 41 | self.advertiser() 42 | self.disconnected() 43 | 44 | elif event == 3: 45 | '''New message received''' 46 | buffer = self.ble.gatts_read(self.rx) 47 | data = buffer.decode('UTF-8').strip() 48 | if not self.message: # keep oldest message 49 | self.message = data 50 | 51 | def get_message(self): 52 | message = self.message 53 | if message: 54 | self.message = '' 55 | return message 56 | 57 | def register(self): 58 | # Nordic UART Service (NUS) 59 | NUS_UUID = '6E400001-B5A3-F393-E0A9-E50E24DCCA9E' 60 | RX_UUID = '6E400002-B5A3-F393-E0A9-E50E24DCCA9E' 61 | TX_UUID = '6E400003-B5A3-F393-E0A9-E50E24DCCA9E' 62 | 63 | BLE_NUS = ubluetooth.UUID(NUS_UUID) 64 | BLE_RX = (ubluetooth.UUID(RX_UUID), ubluetooth.FLAG_WRITE) 65 | BLE_TX = (ubluetooth.UUID(TX_UUID), ubluetooth.FLAG_NOTIFY) 66 | 67 | BLE_UART = (BLE_NUS, (BLE_TX, BLE_RX,)) 68 | SERVICES = (BLE_UART, ) 69 | ((self.tx, self.rx,), ) = self.ble.gatts_register_services(SERVICES) 70 | 71 | def send(self, data): 72 | self.ble.gatts_notify(0, self.tx, data + '\n') 73 | 74 | def advertiser(self): 75 | name = bytes(self.name, 'UTF-8') 76 | adv = b'\x02\x01\x02' + bytearray((len(name) + 1, 0x09)) + name 77 | self.ble.gap_advertise(100, adv) 78 | 79 | -------------------------------------------------------------------------------- /X23/esp32s3-lilygo/tests/config_test.py: -------------------------------------------------------------------------------- 1 | 2 | import camera 3 | import time 4 | import gc 5 | from pmu import cam_power_on 6 | 7 | gc.enable() 8 | 9 | # Switch on camera power controlled by AXP2101 10 | cam_power_on() 11 | 12 | pix = const(17) 13 | frame = const(18) 14 | 15 | # PIXEL FORMAT 16 | PIXFORMAT = { 17 | 'RGB565':1, # 2BPP/RGB565 18 | 'YUV422':2, # 2BPP/YUV422 19 | 'YUV420':3, # 1.5BPP/YUV420 20 | 'GRAYSCALE':4, # 1BPP/GRAYSCALE 21 | 'JPEG':5, # JPEG/COMPRESSED 22 | 'RGB888':6, # 3BPP/RGB888 23 | 'RAW':7, # RAW 24 | 'RGB444':8, # 3BP2P/RGB444 25 | 'RGB555':9, # 3BP2P/RGB555 26 | } 27 | 28 | # FRAME SIZE 29 | FRAMESIZE = { 30 | '96X96':1, # 96x96 31 | 'QQVGA':2, # 160x120 32 | 'QCIF':3, # 176x144 33 | 'HQVGA':4, # 240x176 34 | '240X240':5,# 240x240 35 | 'QVGA':6, # 320x240 36 | 'CIF':7, # 400x296 37 | 'HVGA':8, # 480x320 38 | 'VGA':9, # 640x480 39 | 'SVGA':10, # 800x600 40 | 'XGA':11, # 1024x768 41 | 'HD':12, # 1280x720 42 | 'SXGA':13, # 1280x1024 43 | 'UXGA':14, # 1600x1200 44 | 'FHD':15, # 1920x1080 45 | 'P_HD':16, # 720x1280 46 | 'P_3MP':17, # 864x1536 47 | 'QXGA':18, # 2048x1536 48 | } 49 | 50 | camera.init() 51 | 52 | for p in ( 53 | 'RGB565', # 2BPP/RGB565 54 | 'YUV422', # 2BPP/YUV422 55 | 'YUV420', # 1.5BPP/YUV420 56 | 'GRAYSCALE', # 1BPP/GRAYSCALE 57 | 'JPEG', # JPEG/COMPRESSED 58 | 'RGB888', # 3BPP/RGB888 59 | 'RAW', # RAW 60 | 'RGB444', # 3BP2P/RGB444 61 | 'RGB555'): # 3BP2P/RGB555 62 | n = PIXFORMAT.get(p) 63 | for f in ( 64 | '96X96', # 96x96 65 | 'QQVGA', # 160x120 66 | 'QCIF', # 176x144 67 | 'HQVGA', # 240x176 68 | '240X240',# 240x240 69 | 'QVGA', # 320x240 70 | 'CIF', # 400x296 71 | 'HVGA', # 480x320 72 | 'VGA', # 640x480 73 | 'SVGA', # 800x600 74 | 'XGA', # 1024x768 75 | 'HD', # 1280x720 76 | 'SXGA', # 1280x1024 77 | 'UXGA', # 1600x1200 78 | 'FHD', # 1920x1080 79 | 'P_HD', # 720x1280 80 | 'P_3MP', # 864x1536 81 | 'QXGA'): # 2048x1536 82 | s = FRAMESIZE.get(f) 83 | camera.deinit() 84 | time.sleep(1) 85 | gc.collect() 86 | print('Set', p, f, ':') 87 | camera.conf(pix, n) # set pixelformat 88 | camera.conf(frame, s)# set framesize 89 | try: 90 | ok = camera.init() 91 | if not ok: 92 | print('Camera initialization fail') 93 | break 94 | time.sleep(1) 95 | img = camera.capture() 96 | if img: 97 | print('---> Image size:', len(img)) 98 | else: 99 | print('No image captured') 100 | except Exception as e: 101 | print('ERR:', e) 102 | -------------------------------------------------------------------------------- /html.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # html.py MVC - This is the view V of MVC 26 | 27 | pg = { 28 | # URL: /webcam -> /live, /snap -> /foto, /blitz -> /boto 29 | 'foto':''' 30 | 31 | 32 | ESP32 Camera 33 | 34 | 35 | 36 |
37 | 38 |
39 | 40 | 41 | ''', 42 | 'favicon':''' 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | ''', 51 | 'err':'''Sorry, I can not do that. 52 | ''', 53 | 'none':'''Sorry, nothing there. 54 | ''', 55 | 'no': '''Sorry, unauthorized. 56 | ''', 57 | 'OK':'''OK! 58 | ''', 59 | } 60 | 61 | hdr = { 62 | # start page for streaming 63 | # URL: /webcam, /snap, /blitz 64 | 'foto': """HTTP/1.1 200 OK 65 | Content-Type: text/html; charset=utf-8 66 | Connection: Closed 67 | Content-Length: %d""", 68 | # live stream - 69 | # URL: /live 70 | 'stream': """HTTP/1.1 200 OK 71 | Content-Type: multipart/x-mixed-replace; boundary=frame 72 | Connection: keep-alive 73 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 74 | Expires: Thu, Jan 01 1970 00:00:00 GMT 75 | Pragma: no-cache""", 76 | # live stream - 77 | # URL: 78 | 'frame': """--frame 79 | Content-Type: image/jpeg""", 80 | # still picture - 81 | # URL: /foto 82 | 'pix': """HTTP/1.1 200 OK 83 | Content-Type: image/jpeg 84 | Content-Length: %d""", 85 | # 86 | 'pic': """HTTP/1.1 200 OK 87 | Content-Type: image/jpeg""", 88 | # no content error 89 | # URL: all the rest 90 | 'none': """HTTP/1.1 400 Bad Request 91 | Content-Type: text/plain; charset=utf-8 92 | Connection: Closed 93 | Content-Length: %d""", 94 | # URL: /favicon.ico 95 | 'favicon': """HTTP/1.1 200 OK 96 | Content-Type: text/html; charset=utf-8 97 | Connection: Closed 98 | Cache-Control: max-age=2592000, public 99 | Content-Length: %d""", 100 | # bad request error 101 | # URL: all the rest 102 | 'err': """HTTP/1.1 400 Bad Request 103 | Content-Type: text/plain; charset=utf-8 104 | Connection: Closed 105 | Content-Length: %d""", 106 | # OK 107 | # URL: all the rest 108 | 'OK': """HTTP/1.1 200 OK 109 | Content-Type: text/plain; charset=utf-8 110 | Connection: Closed 111 | Content-Length: %d""", 112 | # NO 113 | # URL: not authenticated 114 | 'NO': """HTTP/1.1 401 Unauthorized 115 | Content-Type: text/plain; charset=utf-8 116 | Connection: Closed 117 | Content-Length: %d""", 118 | } 119 | 120 | -------------------------------------------------------------------------------- /firmwares-20230717/scripts/html.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # html.py MVC - This is the view V of MVC 26 | 27 | pg = { 28 | # URL: /webcam -> /live, /snap -> /foto, /blitz -> /boto 29 | 'foto':''' 30 | 31 | 32 | ESP32 Camera 33 | 34 | 35 | 36 |
37 | 38 |
39 | 40 | 41 | ''', 42 | 'favicon':''' 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | ''', 51 | 'err':'''Sorry, I can not do that. 52 | ''', 53 | 'none':'''Sorry, nothing there. 54 | ''', 55 | 'no': '''Sorry, unauthorized. 56 | ''', 57 | 'OK':'''OK! 58 | ''', 59 | } 60 | 61 | hdr = { 62 | # start page for streaming 63 | # URL: /webcam, /snap, /blitz 64 | 'foto': """HTTP/1.1 200 OK 65 | Content-Type: text/html; charset=utf-8 66 | Connection: Closed 67 | Content-Length: %d""", 68 | # live stream - 69 | # URL: /live 70 | 'stream': """HTTP/1.1 200 OK 71 | Content-Type: multipart/x-mixed-replace; boundary=frame 72 | Connection: keep-alive 73 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 74 | Expires: Thu, Jan 01 1970 00:00:00 GMT 75 | Pragma: no-cache""", 76 | # live stream - 77 | # URL: 78 | 'frame': """--frame 79 | Content-Type: image/jpeg""", 80 | # still picture - 81 | # URL: /foto 82 | 'pix': """HTTP/1.1 200 OK 83 | Content-Type: image/jpeg 84 | Content-Length: %d""", 85 | # 86 | 'pic': """HTTP/1.1 200 OK 87 | Content-Type: image/jpeg""", 88 | # no content error 89 | # URL: all the rest 90 | 'none': """HTTP/1.1 400 Bad Request 91 | Content-Type: text/plain; charset=utf-8 92 | Connection: Closed 93 | Content-Length: %d""", 94 | # URL: /favicon.ico 95 | 'favicon': """HTTP/1.1 200 OK 96 | Content-Type: text/html; charset=utf-8 97 | Connection: Closed 98 | Cache-Control: max-age=2592000, public 99 | Content-Length: %d""", 100 | # bad request error 101 | # URL: all the rest 102 | 'err': """HTTP/1.1 400 Bad Request 103 | Content-Type: text/plain; charset=utf-8 104 | Connection: Closed 105 | Content-Length: %d""", 106 | # OK 107 | # URL: all the rest 108 | 'OK': """HTTP/1.1 200 OK 109 | Content-Type: text/plain; charset=utf-8 110 | Connection: Closed 111 | Content-Length: %d""", 112 | # NO 113 | # URL: not authenticated 114 | 'NO': """HTTP/1.1 401 Unauthorized 115 | Content-Type: text/plain; charset=utf-8 116 | Connection: Closed 117 | Content-Length: %d""", 118 | } 119 | 120 | 121 | -------------------------------------------------------------------------------- /X23/esp32s3-xiao/scripts/cam_config.py: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | # 3 | # Copyright (c) Sharil Tumin 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | #----------------------------------------------------------------------------- 23 | 24 | from micropython import const 25 | 26 | def configure(cam, config): 27 | for key, val in config.items(): 28 | # print(key, val) 29 | cam.conf(key, val) 30 | 31 | #-camera configuration int keys ** DONT EDIT **--------------- 32 | PIN_PWDN = const(0) # power-down 33 | PIN_RESET = const(1) # reset 34 | PIN_XCLK = const(2) 35 | PIN_SIOD = const(3) # SDA 36 | PIN_SIOC = const(4) # SCL 37 | 38 | PIN_D7 = const(5) 39 | PIN_D6 = const(6) 40 | PIN_D5 = const(7) 41 | PIN_D4 = const(8) 42 | PIN_D3 = const(9) 43 | PIN_D2 = const(10) 44 | PIN_D1 = const(11) 45 | PIN_D0 = const(12) 46 | PIN_VSYNC = const(13) 47 | PIN_HREF = const(14) 48 | PIN_PCLK = const(15) 49 | 50 | XCLK_MHZ = const(16) # camera machine clock 51 | PIXFORMAT = const(17) # pixel format 52 | FRAMESIZE = const(18) # framesize 53 | JPEG_QUALITY= const(19) 54 | FB_COUNT = const(20) # framebuffer count > 1 continuous mode (JPEG only) 55 | 56 | PIXFORMAT_RGB565 = const(1) # 2BPP/RGB565 57 | PIXFORMAT_YUV422 = const(2) # 2BPP/YUV422 58 | PIXFORMAT_YUV420 = const(3) # 1.5BPP/YUV420 59 | PIXFORMAT_GRAYSCALE = const(4) # 1BPP/GRAYSCALE 60 | PIXFORMAT_JPEG = const(5) # JPEG/COMPRESSED 61 | PIXFORMAT_RGB888 = const(6) # 3BPP/RGB888 62 | PIXFORMAT_RAW = const(7) # RAW 63 | PIXFORMAT_RGB444 = const(8) # 3BP2P/RGB444 64 | PIXFORMAT_RGB555 = const(9) # 3BP2P/RGB555 65 | 66 | FRAMESIZE_96X96 = const(1) # 96x96 (width x height) 67 | FRAMESIZE_QQVGA = const(2) # 160x120 68 | FRAMESIZE_QCIF = const(3) # 176x144 69 | FRAMESIZE_HQVGA = const(4) # 240x176 70 | FRAMESIZE_240X240 = const(5) # 240x240 71 | FRAMESIZE_QVGA = const(6) # 320x240 72 | FRAMESIZE_CIF = const(7) # 400x296 73 | FRAMESIZE_HVGA = const(8) # 480x320 74 | FRAMESIZE_VGA = const(9) # 640x480 75 | FRAMESIZE_SVGA = const(10) # 800x600 76 | FRAMESIZE_XGA = const(11) # 1024x768 77 | FRAMESIZE_HD = const(12) # 1280x720 78 | FRAMESIZE_SXGA = const(13) # 1280x1024 79 | FRAMESIZE_UXGA = const(14) # 1600x1200 80 | FRAMESIZE_FHD = const(15) # 1920x1080 81 | FRAMESIZE_P_HD = const(16) # 720x1280 82 | FRAMESIZE_P_3MP = const(17) # 864x1536 83 | FRAMESIZE_QXGA = const(18) # 2048x1536 84 | 85 | #------------------------------------------------------------- 86 | # OV2640 Boards configuration below (can edit - add your board) 87 | 88 | # Freenove esp32s3-cam board (default in firmware) 89 | xiao = {PIN_PWDN:-1, 90 | PIN_RESET:-1, 91 | PIN_XCLK:10, 92 | PIN_SIOD:40, 93 | PIN_SIOC:39, 94 | PIN_D7:48, 95 | PIN_D6:11, 96 | PIN_D5:12, 97 | PIN_D4:14, 98 | PIN_D3:16, 99 | PIN_D2:18, 100 | PIN_D1:17, 101 | PIN_D0:15, 102 | PIN_VSYNC:38, 103 | PIN_HREF:47, 104 | PIN_PCLK:13, 105 | XCLK_MHZ:14, 106 | PIXFORMAT:5, 107 | FRAMESIZE:10, 108 | JPEG_QUALITY:12, 109 | FB_COUNT:2, 110 | } 111 | 112 | # add your cam board config below 113 | 114 | -------------------------------------------------------------------------------- /X23/esp32s3-lilygo/scripts/cam_config.py: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | # 3 | # Copyright (c) Sharil Tumin 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | #----------------------------------------------------------------------------- 23 | 24 | from micropython import const 25 | 26 | def configure(cam, config): 27 | for key, val in config.items(): 28 | # print(key, val) 29 | cam.conf(key, val) 30 | 31 | #-camera configuration int keys ** DONT EDIT **--------------- 32 | PIN_PWDN = const(0) # power-down 33 | PIN_RESET = const(1) # reset 34 | PIN_XCLK = const(2) 35 | PIN_SIOD = const(3) # SDA 36 | PIN_SIOC = const(4) # SCL 37 | 38 | PIN_D7 = const(5) 39 | PIN_D6 = const(6) 40 | PIN_D5 = const(7) 41 | PIN_D4 = const(8) 42 | PIN_D3 = const(9) 43 | PIN_D2 = const(10) 44 | PIN_D1 = const(11) 45 | PIN_D0 = const(12) 46 | PIN_VSYNC = const(13) 47 | PIN_HREF = const(14) 48 | PIN_PCLK = const(15) 49 | 50 | XCLK_MHZ = const(16) # camera machine clock 51 | PIXFORMAT = const(17) # pixel format 52 | FRAMESIZE = const(18) # framesize 53 | JPEG_QUALITY= const(19) 54 | FB_COUNT = const(20) # framebuffer count > 1 continuous mode (JPEG only) 55 | 56 | PIXFORMAT_RGB565 = const(1) # 2BPP/RGB565 57 | PIXFORMAT_YUV422 = const(2) # 2BPP/YUV422 58 | PIXFORMAT_YUV420 = const(3) # 1.5BPP/YUV420 59 | PIXFORMAT_GRAYSCALE = const(4) # 1BPP/GRAYSCALE 60 | PIXFORMAT_JPEG = const(5) # JPEG/COMPRESSED 61 | PIXFORMAT_RGB888 = const(6) # 3BPP/RGB888 62 | PIXFORMAT_RAW = const(7) # RAW 63 | PIXFORMAT_RGB444 = const(8) # 3BP2P/RGB444 64 | PIXFORMAT_RGB555 = const(9) # 3BP2P/RGB555 65 | 66 | FRAMESIZE_96X96 = const(1) # 96x96 (width x height) 67 | FRAMESIZE_QQVGA = const(2) # 160x120 68 | FRAMESIZE_QCIF = const(3) # 176x144 69 | FRAMESIZE_HQVGA = const(4) # 240x176 70 | FRAMESIZE_240X240 = const(5) # 240x240 71 | FRAMESIZE_QVGA = const(6) # 320x240 72 | FRAMESIZE_CIF = const(7) # 400x296 73 | FRAMESIZE_HVGA = const(8) # 480x320 74 | FRAMESIZE_VGA = const(9) # 640x480 75 | FRAMESIZE_SVGA = const(10) # 800x600 76 | FRAMESIZE_XGA = const(11) # 1024x768 77 | FRAMESIZE_HD = const(12) # 1280x720 78 | FRAMESIZE_SXGA = const(13) # 1280x1024 79 | FRAMESIZE_UXGA = const(14) # 1600x1200 80 | FRAMESIZE_FHD = const(15) # 1920x1080 81 | FRAMESIZE_P_HD = const(16) # 720x1280 82 | FRAMESIZE_P_3MP = const(17) # 864x1536 83 | FRAMESIZE_QXGA = const(18) # 2048x1536 84 | 85 | #------------------------------------------------------------- 86 | # OV2640 Boards configuration below (can edit - add your board) 87 | 88 | # Lilygo T-camera V1.6 esp32s3-cam board (default in firmware) 89 | lilygo = {PIN_PWDN:-1, 90 | PIN_RESET:39, 91 | PIN_XCLK:38, 92 | PIN_SIOD:5, 93 | PIN_SIOC:4, 94 | PIN_D7:9, 95 | PIN_D6:10, 96 | PIN_D5:11, 97 | PIN_D4:13, 98 | PIN_D3:21, 99 | PIN_D2:48, 100 | PIN_D1:47, 101 | PIN_D0:14, 102 | PIN_VSYNC:8, 103 | PIN_HREF:18, 104 | PIN_PCLK:12, 105 | XCLK_MHZ:14, 106 | PIXFORMAT:5, 107 | FRAMESIZE:10, 108 | JPEG_QUALITY:12, 109 | FB_COUNT:2, 110 | } 111 | 112 | # add your cam board config below 113 | 114 | -------------------------------------------------------------------------------- /X23/esp32s3-freenove/scripts/cam_config.py: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | # 3 | # Copyright (c) Sharil Tumin 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | #----------------------------------------------------------------------------- 23 | 24 | from micropython import const 25 | 26 | def configure(cam, config): 27 | for key, val in config.items(): 28 | # print(key, val) 29 | cam.conf(key, val) 30 | 31 | #-camera configuration int keys ** DONT EDIT **--------------- 32 | PIN_PWDN = const(0) # power-down 33 | PIN_RESET = const(1) # reset 34 | PIN_XCLK = const(2) 35 | PIN_SIOD = const(3) # SDA 36 | PIN_SIOC = const(4) # SCL 37 | 38 | PIN_D7 = const(5) 39 | PIN_D6 = const(6) 40 | PIN_D5 = const(7) 41 | PIN_D4 = const(8) 42 | PIN_D3 = const(9) 43 | PIN_D2 = const(10) 44 | PIN_D1 = const(11) 45 | PIN_D0 = const(12) 46 | PIN_VSYNC = const(13) 47 | PIN_HREF = const(14) 48 | PIN_PCLK = const(15) 49 | 50 | XCLK_MHZ = const(16) # camera machine clock 51 | PIXFORMAT = const(17) # pixel format 52 | FRAMESIZE = const(18) # framesize 53 | JPEG_QUALITY= const(19) 54 | FB_COUNT = const(20) # framebuffer count > 1 continuous mode (JPEG only) 55 | 56 | PIXFORMAT_RGB565 = const(1) # 2BPP/RGB565 57 | PIXFORMAT_YUV422 = const(2) # 2BPP/YUV422 58 | PIXFORMAT_YUV420 = const(3) # 1.5BPP/YUV420 59 | PIXFORMAT_GRAYSCALE = const(4) # 1BPP/GRAYSCALE 60 | PIXFORMAT_JPEG = const(5) # JPEG/COMPRESSED 61 | PIXFORMAT_RGB888 = const(6) # 3BPP/RGB888 62 | PIXFORMAT_RAW = const(7) # RAW 63 | PIXFORMAT_RGB444 = const(8) # 3BP2P/RGB444 64 | PIXFORMAT_RGB555 = const(9) # 3BP2P/RGB555 65 | 66 | FRAMESIZE_96X96 = const(1) # 96x96 (width x height) 67 | FRAMESIZE_QQVGA = const(2) # 160x120 68 | FRAMESIZE_QCIF = const(3) # 176x144 69 | FRAMESIZE_HQVGA = const(4) # 240x176 70 | FRAMESIZE_240X240 = const(5) # 240x240 71 | FRAMESIZE_QVGA = const(6) # 320x240 72 | FRAMESIZE_CIF = const(7) # 400x296 73 | FRAMESIZE_HVGA = const(8) # 480x320 74 | FRAMESIZE_VGA = const(9) # 640x480 75 | FRAMESIZE_SVGA = const(10) # 800x600 76 | FRAMESIZE_XGA = const(11) # 1024x768 77 | FRAMESIZE_HD = const(12) # 1280x720 78 | FRAMESIZE_SXGA = const(13) # 1280x1024 79 | FRAMESIZE_UXGA = const(14) # 1600x1200 80 | FRAMESIZE_FHD = const(15) # 1920x1080 81 | FRAMESIZE_P_HD = const(16) # 720x1280 82 | FRAMESIZE_P_3MP = const(17) # 864x1536 83 | FRAMESIZE_QXGA = const(18) # 2048x1536 84 | 85 | #------------------------------------------------------------- 86 | # OV2640 Boards configuration below (can edit - add your board) 87 | 88 | # Freenove esp32s3-cam board (default in firmware) 89 | freenove = {PIN_PWDN:-1, 90 | PIN_RESET:-1, 91 | PIN_XCLK:15, 92 | PIN_SIOD:4, 93 | PIN_SIOC:5, 94 | PIN_D7:16, 95 | PIN_D6:17, 96 | PIN_D5:18, 97 | PIN_D4:12, 98 | PIN_D3:10, 99 | PIN_D2:8, 100 | PIN_D1:9, 101 | PIN_D0:11, 102 | PIN_VSYNC:6, 103 | PIN_HREF:7, 104 | PIN_PCLK:13, 105 | XCLK_MHZ:14, 106 | PIXFORMAT:5, 107 | FRAMESIZE:10, 108 | JPEG_QUALITY:12, 109 | FB_COUNT:2, 110 | } 111 | 112 | # add your cam board config below 113 | 114 | -------------------------------------------------------------------------------- /X23/esp32-aiThinker/scripts/cam_config.py: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | # 3 | # Copyright (c) Sharil Tumin 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | #----------------------------------------------------------------------------- 23 | 24 | from micropython import const 25 | 26 | def configure(cam, config): 27 | for key, val in config.items(): 28 | # print(key, val) 29 | cam.conf(key, val) 30 | 31 | #-camera configuration int keys ** DONT EDIT **--------------- 32 | PIN_PWDN = const(0) # power-down 33 | PIN_RESET = const(1) # reset 34 | PIN_XCLK = const(2) 35 | PIN_SIOD = const(3) # SDA 36 | PIN_SIOC = const(4) # SCL 37 | 38 | PIN_D7 = const(5) 39 | PIN_D6 = const(6) 40 | PIN_D5 = const(7) 41 | PIN_D4 = const(8) 42 | PIN_D3 = const(9) 43 | PIN_D2 = const(10) 44 | PIN_D1 = const(11) 45 | PIN_D0 = const(12) 46 | PIN_VSYNC = const(13) 47 | PIN_HREF = const(14) 48 | PIN_PCLK = const(15) 49 | 50 | XCLK_MHZ = const(16) # camera machine clock 51 | PIXFORMAT = const(17) # pixel format 52 | FRAMESIZE = const(18) # framesize 53 | JPEG_QUALITY= const(19) 54 | FB_COUNT = const(20) # framebuffer count > 1 continuous mode (JPEG only) 55 | 56 | PIXFORMAT_RGB565 = const(1) # 2BPP/RGB565 57 | PIXFORMAT_YUV422 = const(2) # 2BPP/YUV422 58 | PIXFORMAT_YUV420 = const(3) # 1.5BPP/YUV420 59 | PIXFORMAT_GRAYSCALE = const(4) # 1BPP/GRAYSCALE 60 | PIXFORMAT_JPEG = const(5) # JPEG/COMPRESSED 61 | PIXFORMAT_RGB888 = const(6) # 3BPP/RGB888 62 | PIXFORMAT_RAW = const(7) # RAW 63 | PIXFORMAT_RGB444 = const(8) # 3BP2P/RGB444 64 | PIXFORMAT_RGB555 = const(9) # 3BP2P/RGB555 65 | 66 | FRAMESIZE_96X96 = const(1) # 96x96 (width x height) 67 | FRAMESIZE_QQVGA = const(2) # 160x120 68 | FRAMESIZE_QCIF = const(3) # 176x144 69 | FRAMESIZE_HQVGA = const(4) # 240x176 70 | FRAMESIZE_240X240 = const(5) # 240x240 71 | FRAMESIZE_QVGA = const(6) # 320x240 72 | FRAMESIZE_CIF = const(7) # 400x296 73 | FRAMESIZE_HVGA = const(8) # 480x320 74 | FRAMESIZE_VGA = const(9) # 640x480 75 | FRAMESIZE_SVGA = const(10) # 800x600 76 | FRAMESIZE_XGA = const(11) # 1024x768 77 | FRAMESIZE_HD = const(12) # 1280x720 78 | FRAMESIZE_SXGA = const(13) # 1280x1024 79 | FRAMESIZE_UXGA = const(14) # 1600x1200 80 | FRAMESIZE_FHD = const(15) # 1920x1080 81 | FRAMESIZE_P_HD = const(16) # 720x1280 82 | FRAMESIZE_P_3MP = const(17) # 864x1536 83 | FRAMESIZE_QXGA = const(18) # 2048x1536 84 | 85 | #------------------------------------------------------------- 86 | # OV2640 Boards configuration below (can edit - add your board) 87 | 88 | # AI-Thinker esp32-cam board 89 | ai_thinker = {PIN_PWDN:32, 90 | PIN_RESET:-1, 91 | PIN_XCLK:0, 92 | PIN_SIOD:26, 93 | PIN_SIOC:27, 94 | PIN_D7:35, 95 | PIN_D6:34, 96 | PIN_D5:39, 97 | PIN_D4:36, 98 | PIN_D3:21, 99 | PIN_D2:19, 100 | PIN_D1:18, 101 | PIN_D0:5, 102 | PIN_VSYNC:25, 103 | PIN_HREF:23, 104 | PIN_PCLK:22, 105 | XCLK_MHZ:16, 106 | PIXFORMAT:5, 107 | FRAMESIZE:10, 108 | JPEG_QUALITY:10, 109 | FB_COUNT:1, 110 | } 111 | 112 | # add your cam board config below 113 | 114 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32/AI-Thinker-OV2640/scripts/streaming_server.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # run this on ESP32 Camera 26 | 27 | import esp 28 | # from bluetooth import BLE 29 | from Wifi import Sta 30 | import socket as soc 31 | import camera 32 | from time import sleep 33 | 34 | hdr = { 35 | # live stream - 36 | # URL: /live 37 | 'stream': """HTTP/1.1 200 OK 38 | Content-Type: multipart/x-mixed-replace; boundary=kaki5 39 | Connection: keep-alive 40 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 41 | Expires: Thu, Jan 01 1970 00:00:00 GMT 42 | Pragma: no-cache""", 43 | # live stream - 44 | # URL: 45 | 'frame': """--kaki5 46 | Content-Type: image/jpeg"""} 47 | 48 | UID = const('ali') # authentication user. Whatever you want 49 | PWD = const('Baba40Robrs') # authentication password. Whatever you want 50 | 51 | cam = camera.init() # Camera 52 | print("Camera ready?: ", cam) 53 | 54 | # connect to access point 55 | sta = Sta() # Station mode (i.e. need WiFi router) 56 | # sta.wlan.disconnect() # disconnect from previous connection 57 | AP = const('dlink-3530') # Your SSID 58 | PW = const('cabbp73520') # Your password 59 | sta.connect(AP, PW) # connet to dlink 60 | sta.wait() 61 | 62 | # wait for WiFi 63 | con = () 64 | for i in range(5): 65 | if sta.wlan.isconnected():con=sta.status();break 66 | else: print("WIFI not ready. Wait...");sleep(2) 67 | else: 68 | print("WIFI not ready") 69 | 70 | if con and cam: # WiFi and camera are ready 71 | if cam: 72 | # set preffered camera setting 73 | camera.framesize(10) # frame size 800X600 (1.33 espect ratio) 74 | camera.contrast(2) # increase contrast 75 | camera.speffect(2) # jpeg grayscale 76 | if con: 77 | # TCP server 78 | port = 80 79 | addr = soc.getaddrinfo('0.0.0.0', port)[0][-1] 80 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 81 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 82 | s.bind(addr) 83 | s.listen(1) 84 | # s.settimeout(5.0) 85 | while True: 86 | cs, ca = s.accept() # wait for client connect 87 | print('Request from:', ca) 88 | w = cs.recv(200) # blocking 89 | (_, uid, pwd) = w.decode().split('\r\n')[0].split()[1].split('/') 90 | # print(_, uid, pwd) 91 | if not (uid==UID and pwd==PWD): 92 | print('Not authenticated') 93 | cs.close() 94 | continue 95 | # We are authenticated, so continue serving 96 | cs.write(b'%s\r\n\r\n' % hdr['stream']) 97 | pic=camera.capture 98 | put=cs.write 99 | hr=hdr['frame'] 100 | while True: 101 | # once connected and authenticated just send the jpg data 102 | # client use HTTP protocol (not RTSP) 103 | try: 104 | put(b'%s\r\n\r\n' % hr) 105 | put(pic()) 106 | put(b'\r\n') # send and flush the send buffer 107 | except Exception as e: 108 | print('TCP send error', e) 109 | cs.close() 110 | break 111 | else: 112 | if not con: 113 | print("WiFi not connected.") 114 | if not cam: 115 | print("Camera not ready.") 116 | else: 117 | camera.deinit() 118 | print("System not ready. Please restart") 119 | 120 | print('System aborted') 121 | -------------------------------------------------------------------------------- /X23/opencv_scripts/hands_detection.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # run this on Linux PC with opencv-python module 26 | 27 | import cv2 28 | from cvzone.HandTrackingModule import HandDetector 29 | 30 | 31 | # Hands = HandDetector(staticMode=False, maxHands=2, modelComplexity=1, detectionCon=0.5, minTrackCon=0.5) 32 | Hands = HandDetector(detectionCon=0.5) 33 | # if not detected try move your hands away from the camera 34 | 35 | # Change this to your board IP 36 | # Try first with web-browser, you will see image stream if OK 37 | # http-based image streaming server 38 | 39 | # url = 'http://192.168.4.74/free/Hi-Nove-La' # freenove 40 | # url = 'http://192.168.4.70/xiao/Hi-Xiao-Ling' # xio 41 | # url = 'http://192.168.4.71/lily/Hi-Lily-Goen' # lilygo 42 | url = 'http://192.168.4.97/ait/Hi-AIT-123' # esp32 AiThinker 43 | 44 | vid = cv2.VideoCapture(url) # open webcam capture 45 | 46 | dropped = 0 # drop frames count 47 | while True: 48 | ret, frame = vid.read() # get frame-by-frame 49 | if frame is not None: 50 | if dropped > 0: dropped = 0 # reset 51 | hands, frame = Hands.findHands(frame, draw=True, flipType=True) 52 | # Check if any hands are detected 53 | if hands: 54 | # Information for the first hand detected 55 | hand1 = hands[0] # Get the first hand detected 56 | # lmList1 = hand1["lmList"] # List of 21 landmarks for the first hand 57 | bbox1 = hand1["bbox"] # Bounding box around the first hand 58 | # (x,y,w,h coordinates) 59 | center1 = hand1['center'] # Center coordinates of the first hand 60 | handType1 = hand1["type"] # Type of the first hand ("Left" or "Right") 61 | 62 | # Count the number of fingers up for the first hand 63 | # fingers1 = Hands.fingersUp(hand1) 64 | # print(f'H1 = {fingers1.count(1)}', end=" ") 65 | 66 | # Calculate distance between specific landmarks on the first hand 67 | # and draw it on the image 68 | # length, info, frame = Hands.findDistance(lmList1[8][0:2], lmList1[12][0:2], frame, color=(255, 0, 255), scale=10) 69 | 70 | # Check if a second hand is detected 71 | if len(hands) == 2: 72 | # Information for the second hand 73 | hand2 = hands[1] 74 | # lmList2 = hand2["lmList"] 75 | bbox2 = hand2["bbox"] 76 | center2 = hand2['center'] 77 | handType2 = hand2["type"] 78 | 79 | # Count the number of fingers up for the second hand 80 | # fingers2 = Hands.fingersUp(hand2) 81 | # print(f'H2 = {fingers2.count(1)}', end=" ") 82 | 83 | # Calculate distance between the index fingers of both hands 84 | # and draw it on the image 85 | # length, info, frame = Hands.findDistance(lmList1[8][0:2], lmList2[8][0:2], frame, color=(255, 0, 0), scale=10) 86 | 87 | # print(" ") # New line for better readability of the printed output 88 | # show image 89 | cv2.imshow('Hands',frame) # display frame 90 | # define abort key 91 | if cv2.waitKey(22) & 0xFF == ord('q'): # press q to quit 92 | break 93 | else: 94 | dropped += 1 95 | if dropped > 100: 96 | print("Server is down") 97 | break 98 | 99 | # Done, clear all resources 100 | vid.release() 101 | cv2.destroyAllWindows() 102 | print("Video stop") 103 | 104 | -------------------------------------------------------------------------------- /firmwares-20230521/scripts/config.py: -------------------------------------------------------------------------------- 1 | 2 | #-camera configuration int keys ** DONT EDIT **--------------- 3 | PIN_PWDN = const(0) # power-down 4 | PIN_RESET = const(1) # reset 5 | PIN_XCLK = const(2) 6 | PIN_SIOD = const(3) # SDA 7 | PIN_SIOC = const(4) # SCL 8 | 9 | PIN_D7 = const(5) 10 | PIN_D6 = const(6) 11 | PIN_D5 = const(7) 12 | PIN_D4 = const(8) 13 | PIN_D3 = const(9) 14 | PIN_D2 = const(10) 15 | PIN_D1 = const(11) 16 | PIN_D0 = const(12) 17 | PIN_VSYNC = const(13) 18 | PIN_HREF = const(14) 19 | PIN_PCLK = const(15) 20 | 21 | XCLK_MHZ = const(16) # camera machine clock 22 | PIXFORMAT = const(17) # pixel format 23 | FRAMESIZE = const(18) # framesize 24 | JPEG_QUALITY= const(19) 25 | FB_COUNT = const(20) # framebuffer count > 1 continuous mode (JPEG only) 26 | 27 | #------------------------------------------------------------- 28 | 29 | # OV2640 Boards configuration below (can edit - add your board) 30 | 31 | # AI-Thinker esp32-cam board 32 | ai_thinker = {PIN_PWDN:32, 33 | PIN_RESET:-1, 34 | PIN_XCLK:0, 35 | PIN_SIOD:26, 36 | PIN_SIOC:27, 37 | PIN_D7:35, 38 | PIN_D6:34, 39 | PIN_D5:39, 40 | PIN_D4:36, 41 | PIN_D3:21, 42 | PIN_D2:19, 43 | PIN_D1:18, 44 | PIN_D0:5, 45 | PIN_VSYNC:25, 46 | PIN_HREF:23, 47 | PIN_PCLK:22, 48 | XCLK_MHZ:16, 49 | PIXFORMAT:5, 50 | FRAMESIZE:10, 51 | JPEG_QUALITY:10, 52 | FB_COUNT:1, 53 | } 54 | 55 | # New 2022 esp32vrover dev 56 | esp_eye = {PIN_PWDN:-1, 57 | PIN_RESET:-1, 58 | PIN_XCLK:4, 59 | PIN_SIOD:18, 60 | PIN_SIOC:23, 61 | PIN_D7:36, 62 | PIN_D6:37, 63 | PIN_D5:38, 64 | PIN_D4:39, 65 | PIN_D3:35, 66 | PIN_D2:14, 67 | PIN_D1:13, 68 | PIN_D0:34, 69 | PIN_VSYNC:5, 70 | PIN_HREF:27, 71 | PIN_PCLK:25, 72 | XCLK_MHZ:16, 73 | PIXFORMAT:5, 74 | FRAMESIZE:10, 75 | JPEG_QUALITY:10, 76 | FB_COUNT:1, 77 | } 78 | 79 | # esp32 wrover dev 80 | wrover_dev = {PIN_PWDN:32, 81 | PIN_RESET:-1, 82 | PIN_XCLK:21, 83 | PIN_SIOD:26, 84 | PIN_SIOC:27, 85 | PIN_D7:35, 86 | PIN_D6:34, 87 | PIN_D5:39, 88 | PIN_D4:36, 89 | PIN_D3:19, 90 | PIN_D2:18, 91 | PIN_D1:5, 92 | PIN_D0:4, 93 | PIN_VSYNC:25, 94 | PIN_HREF:23, 95 | PIN_PCLK:22, 96 | XCLK_MHZ:12, 97 | PIXFORMAT:5, 98 | FRAMESIZE:10, 99 | JPEG_QUALITY:10, 100 | FB_COUNT:1, 101 | } 102 | 103 | # Test 104 | wrover_test = {PIN_PWDN:-1, 105 | PIN_RESET:-1, 106 | PIN_XCLK:21, 107 | PIN_SIOD:26, 108 | PIN_SIOC:27, 109 | PIN_D7:35, 110 | PIN_D6:34, 111 | PIN_D5:39, 112 | PIN_D4:36, 113 | PIN_D3:19, 114 | PIN_D2:18, 115 | PIN_D1:5, 116 | PIN_D0:4, 117 | PIN_VSYNC:25, 118 | PIN_HREF:23, 119 | PIN_PCLK:22, 120 | XCLK_MHZ:12, 121 | PIXFORMAT:5, 122 | FRAMESIZE:10, 123 | JPEG_QUALITY:10, 124 | FB_COUNT:1, 125 | } 126 | 127 | # Red Board (has internal clock for camera set at 12Mhz) 128 | red_board = {PIN_PWDN:32, # 129 | PIN_RESET:-1, 130 | PIN_XCLK:-1, # internal sensor clock 131 | PIN_SIOD:26, 132 | PIN_SIOC:27, 133 | PIN_D7:35, 134 | PIN_D6:34, 135 | PIN_D5:39, 136 | PIN_D4:36, 137 | PIN_D3:21, 138 | PIN_D2:19, 139 | PIN_D1:18, 140 | PIN_D0:5, 141 | PIN_VSYNC:25, 142 | PIN_HREF:23, 143 | PIN_PCLK:22, 144 | XCLK_MHZ:12, # the board has 12Mhz intrenal clock (MUST set to 12) 145 | PIXFORMAT:5, 146 | FRAMESIZE:10, 147 | JPEG_QUALITY:10, 148 | FB_COUNT:1, 149 | } 150 | 151 | def configure(cam, config): 152 | for key, val in config.items(): 153 | # print(key, val) 154 | cam.conf(key, val) 155 | 156 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/XIAO-Sense-OV2640/scripts/streaming_server.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # run this on ESP32 Camera 26 | 27 | import esp 28 | # from bluetooth import BLE 29 | from Wifi import Sta 30 | import socket as soc 31 | import camera 32 | from time import sleep 33 | 34 | hdr = { 35 | # live stream - 36 | # URL: /live 37 | 'stream': """HTTP/1.1 200 OK 38 | Content-Type: multipart/x-mixed-replace; boundary=kaki5 39 | Connection: keep-alive 40 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 41 | Expires: Thu, Jan 01 1970 00:00:00 GMT 42 | Pragma: no-cache""", 43 | # live stream - 44 | # URL: 45 | 'frame': """--kaki5 46 | Content-Type: image/jpeg"""} 47 | 48 | # esp.osdebug(None) # turn off debugging log. Uncomment to show debugging log 49 | 50 | # BLE().active(False) # disable ble 51 | 52 | UID = const('xiao') # authentication user. Whatever you want 53 | PWD = const('Hi-Xiao-Ling') # authentication password. Whatever you want 54 | 55 | cam = camera.init() # Camera 56 | print("Camera ready?: ", cam) 57 | 58 | # connect to access point 59 | sta = Sta() # Station mode (i.e. need WiFi router) 60 | # sta.wlan.disconnect() # disconnect from previous connection 61 | AP = const('your-ssid-3530') # Your SSID 62 | PW = const('your-wifi-pwd') # Your password 63 | sta.connect(AP, PW) # connet to dlink 64 | sta.wait() 65 | 66 | # wait for WiFi 67 | con = () 68 | for i in range(5): 69 | if sta.wlan.isconnected():con=sta.status();break 70 | else: print("WIFI not ready. Wait...");sleep(2) 71 | else: 72 | print("WIFI not ready") 73 | 74 | if con and cam: # WiFi and camera are ready 75 | if cam: 76 | # set preffered camera setting 77 | camera.framesize(10) # frame size 800X600 (1.33 espect ratio) 78 | camera.contrast(2) # increase contrast 79 | camera.speffect(2) # jpeg grayscale 80 | if con: 81 | # TCP server 82 | port = 80 83 | addr = soc.getaddrinfo('0.0.0.0', port)[0][-1] 84 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 85 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 86 | s.bind(addr) 87 | s.listen(1) 88 | # s.settimeout(5.0) 89 | while True: 90 | cs, ca = s.accept() # wait for client connect 91 | print('Request from:', ca) 92 | w = cs.recv(200) # blocking 93 | (_, uid, pwd) = w.decode().split('\r\n')[0].split()[1].split('/') 94 | # print(_, uid, pwd) 95 | if not (uid==UID and pwd==PWD): 96 | print('Not authenticated') 97 | cs.close() 98 | continue 99 | # We are authenticated, so continue serving 100 | cs.write(b'%s\r\n\r\n' % hdr['stream']) 101 | pic=camera.capture 102 | put=cs.write 103 | hr=hdr['frame'] 104 | while True: 105 | # once connected and authenticated just send the jpg data 106 | # client use HTTP protocol (not RTSP) 107 | try: 108 | put(b'%s\r\n\r\n' % hr) 109 | put(pic()) 110 | put(b'\r\n') # send and flush the send buffer 111 | except Exception as e: 112 | print('TCP send error', e) 113 | cs.close() 114 | break 115 | else: 116 | if not con: 117 | print("WiFi not connected.") 118 | if not cam: 119 | print("Camera not ready.") 120 | else: 121 | camera.deinit() 122 | print("System not ready. Please restart") 123 | 124 | print('System aborted') 125 | -------------------------------------------------------------------------------- /firmwares-20230717/ESP32-S3/LILYGO-T-Camera-OV2640/scripts/streaming_server.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # run this on ESP32S2 Lilygo T-Camera 26 | 27 | import esp 28 | from Wifi import Sta 29 | import socket as soc 30 | import camera 31 | from time import sleep 32 | from pmu import cam_power_on 33 | 34 | hdr = { 35 | # live stream - 36 | # URL: /live 37 | 'stream': """HTTP/1.1 200 OK 38 | Content-Type: multipart/x-mixed-replace; boundary=kaki5 39 | Connection: keep-alive 40 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 41 | Expires: Thu, Jan 01 1970 00:00:00 GMT 42 | Pragma: no-cache""", 43 | # live stream - 44 | # URL: 45 | 'frame': """--kaki5 46 | Content-Type: image/jpeg"""} 47 | 48 | esp.osdebug(None) # turn off debugging log. Uncomment to show debugging log 49 | 50 | # Switch on camera power controlled by AXP2101 51 | cam_power_on() 52 | 53 | UID = const('lily') # authentication user. Whatever you want 54 | PWD = const('Hi-Lily-Goen') # authentication password. Whatever you want 55 | 56 | # camera.conf(16, 10) # set xclk rate to 10Mhz 57 | cam = camera.init() # Camera 58 | print("Camera ready?: ", cam) 59 | 60 | # connect to access point 61 | sta = Sta() # Station mode (i.e. need WiFi router) 62 | # sta.wlan.disconnect() # disconnect from previous connection 63 | AP = const('you-ssid-3530') # Your SSID 64 | PW = const('you-wifi-pwd') # Your password 65 | sta.connect(AP, PW) # connet to dlink 66 | sta.wait() 67 | 68 | # wait for WiFi 69 | con = () 70 | for i in range(5): 71 | if sta.wlan.isconnected():con=sta.status();break 72 | else: print("WIFI not ready. Wait...");sleep(2) 73 | else: 74 | print("WIFI not ready") 75 | 76 | if con and cam: # WiFi and camera are ready 77 | if cam: 78 | # set preffered camera setting 79 | camera.framesize(10) # frame size 800X600 (1.33 espect ratio) 80 | camera.contrast(2) # increase contrast 81 | camera.speffect(2) # jpeg grayscale 82 | if con: 83 | # TCP server 84 | port = 80 85 | addr = soc.getaddrinfo('0.0.0.0', port)[0][-1] 86 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 87 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 88 | s.bind(addr) 89 | s.listen(1) 90 | # s.settimeout(5.0) 91 | while True: 92 | cs, ca = s.accept() # wait for client connect 93 | print('Request from:', ca) 94 | w = cs.recv(200) # blocking 95 | (_, uid, pwd) = w.decode().split('\r\n')[0].split()[1].split('/') 96 | # print(_, uid, pwd) 97 | if not (uid==UID and pwd==PWD): 98 | print('Not authenticated') 99 | cs.close() 100 | continue 101 | # We are authenticated, so continue serving 102 | cs.write(b'%s\r\n\r\n' % hdr['stream']) 103 | pic=camera.capture 104 | put=cs.write 105 | hr=hdr['frame'] 106 | while True: 107 | # once connected and authenticated just send the jpg data 108 | # client use HTTP protocol (not RTSP) 109 | try: 110 | put(b'%s\r\n\r\n' % hr) 111 | put(pic()) 112 | put(b'\r\n') # send and flush the send buffer 113 | except Exception as e: 114 | print('TCP send error', e) 115 | cs.close() 116 | break 117 | else: 118 | if not con: 119 | print("WiFi not connected.") 120 | if not cam: 121 | print("Camera not ready.") 122 | else: 123 | camera.deinit() 124 | print("System not ready. Please restart") 125 | 126 | print('System aborted') 127 | -------------------------------------------------------------------------------- /X23/esp32s3-xiao/scripts/streaming_server.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # run this on ESP32 Camera 26 | 27 | import esp 28 | # from bluetooth import BLE 29 | import network 30 | from time import sleep 31 | import socket as soc 32 | import camera 33 | import cam_config as cc 34 | from auth import AP, PW, UID, PWD 35 | 36 | hdr = { 37 | # live stream - 38 | # URL: /live 39 | 'stream': """HTTP/1.1 200 OK 40 | Content-Type: multipart/x-mixed-replace; boundary=kaki5 41 | Connection: keep-alive 42 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 43 | Expires: Thu, Jan 01 1970 00:00:00 GMT 44 | Pragma: no-cache""", 45 | # live stream - 46 | # URL: 47 | 'frame': """--kaki5 48 | Content-Type: image/jpeg"""} 49 | 50 | # esp.osdebug(None) # turn off debugging log. Uncomment to show debugging log 51 | 52 | # BLE().active(False) # disable ble 53 | 54 | # URL with the above UID and PWD, eg 55 | # http://192.168.4.74/free/Hi-Nove-La 56 | 57 | # default config is xiao 58 | cc.configure(camera, cc.xiao) # not really needed - default in firmware is xiao 59 | 60 | # both pixformat and framesize MUST before camera.init 61 | # after camera.init() you need to do camera.deinit() if you want to 62 | # change pixformat and or framesize, and camera.init() again. 63 | 64 | #camera.conf(cc.FRAMESIZE,cc.FRAMESIZE_SVGA) # good for webstreaming 65 | camera.conf(cc.FRAMESIZE,cc.FRAMESIZE_QVGA) # good for opencv 66 | cam = camera.init() 67 | print("Camera ready?: ", cam) 68 | 69 | # connect to access point 70 | network.WLAN(network.AP_IF).active(False) 71 | sta = network.WLAN(network.STA_IF) 72 | sta.active(True) 73 | 74 | con = () 75 | if not sta.isconnected(): 76 | sta.connect(AP, PW) # connect to AP with PW 77 | # wait for WiFi 78 | for i in range(5): 79 | if sta.isconnected(): con = sta.ifconfig(); break 80 | else: print("WIFI not ready. Wait...");sleep(2) 81 | else: 82 | con = sta.ifconfig() 83 | 84 | if con: 85 | print("WIFI ready") 86 | print(con) 87 | 88 | if con and cam: # WiFi and camera are ready 89 | if cam: 90 | # set preffered camera setting 91 | camera.contrast(2) # increase contrast 92 | camera.speffect(2) # jpeg grayscale 93 | if con: 94 | # TCP server 95 | port = 80 96 | addr = soc.getaddrinfo('0.0.0.0', port)[0][-1] 97 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 98 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 99 | s.bind(addr) 100 | s.listen(1) 101 | # s.settimeout(5.0) 102 | while True: # start HTTP-based streaming server 103 | cs, ca = s.accept() # wait for client connect 104 | print('Request from:', ca) 105 | w = cs.recv(200) # blocking 106 | (_, uid, pwd) = w.decode().split('\r\n')[0].split()[1].split('/') 107 | # print(_, uid, pwd) 108 | if not (uid==UID and pwd==PWD): 109 | print('Not authenticated') 110 | cs.close() 111 | continue 112 | # We are authenticated, so continue serving 113 | cs.write(b'%s\r\n\r\n' % hdr['stream']) 114 | pic=camera.capture 115 | put=cs.write 116 | hr=hdr['frame'] 117 | while True: 118 | # once connected and authenticated just send the jpg data 119 | # client use HTTP protocol (not RTSP) 120 | try: 121 | put(b'%s\r\n\r\n' % hr) 122 | put(pic()) 123 | put(b'\r\n') # send and flush the send buffer 124 | except Exception as e: 125 | print('TCP send error', e) 126 | cs.close() 127 | break 128 | else: 129 | if not con: 130 | print("WiFi not connected.") 131 | if not cam: 132 | print("Camera not ready. Please do machine.reset()") 133 | else: 134 | camera.deinit() 135 | print("System not ready. Please restart") 136 | 137 | print('System aborted') 138 | 139 | -------------------------------------------------------------------------------- /X23/esp32-aiThinker/scripts/streaming_server.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # run this on ESP32 Camera 26 | 27 | import esp 28 | # from bluetooth import BLE 29 | import network 30 | from time import sleep 31 | import socket as soc 32 | import camera 33 | import cam_config as cc 34 | from auth import AP, PW, UID, PWD 35 | 36 | hdr = { 37 | # live stream - 38 | # URL: /live 39 | 'stream': """HTTP/1.1 200 OK 40 | Content-Type: multipart/x-mixed-replace; boundary=kaki5 41 | Connection: keep-alive 42 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 43 | Expires: Thu, Jan 01 1970 00:00:00 GMT 44 | Pragma: no-cache""", 45 | # live stream - 46 | # URL: 47 | 'frame': """--kaki5 48 | Content-Type: image/jpeg"""} 49 | 50 | # esp.osdebug(None) # turn off debugging log. Uncomment to show debugging log 51 | 52 | # BLE().active(False) # disable ble 53 | 54 | # URL with the above UID and PWD, eg 55 | # http://192.168.4.97/ait/Hi-AIT-123 56 | 57 | # default config is xiao 58 | cc.configure(camera, cc.ai_thinker) # not really needed - default in firmware is ai_thinker 59 | 60 | # both pixformat and framesize MUST before camera.init 61 | # after camera.init() you need to do camera.deinit() if you want to 62 | # change pixformat and or framesize, and camera.init() again. 63 | 64 | #camera.conf(cc.FRAMESIZE,cc.FRAMESIZE_SVGA) # good for webstreaming 65 | camera.conf(cc.FRAMESIZE,cc.FRAMESIZE_QVGA) # good for opencv 66 | cam = camera.init() 67 | print("Camera ready?: ", cam) 68 | 69 | # connect to access point 70 | network.WLAN(network.AP_IF).active(False) 71 | sta = network.WLAN(network.STA_IF) 72 | sta.active(True) 73 | 74 | con = () 75 | if not sta.isconnected(): 76 | sta.connect(AP, PW) # connect to AP with PW 77 | # wait for WiFi 78 | for i in range(5): 79 | if sta.isconnected(): con = sta.ifconfig(); break 80 | else: print("WIFI not ready. Wait...");sleep(2) 81 | else: 82 | con = sta.ifconfig() 83 | 84 | if con: 85 | print("WIFI ready") 86 | print(con) 87 | 88 | if con and cam: # WiFi and camera are ready 89 | if cam: 90 | # set preffered camera setting 91 | camera.contrast(2) # increase contrast 92 | camera.speffect(2) # jpeg grayscale 93 | if con: 94 | # TCP server 95 | port = 80 96 | addr = soc.getaddrinfo('0.0.0.0', port)[0][-1] 97 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 98 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 99 | s.bind(addr) 100 | s.listen(1) 101 | # s.settimeout(5.0) 102 | while True: # start HTTP-based streaming server 103 | cs, ca = s.accept() # wait for client connect 104 | print('Request from:', ca) 105 | w = cs.recv(200) # blocking 106 | (_, uid, pwd) = w.decode().split('\r\n')[0].split()[1].split('/') 107 | # print(_, uid, pwd) 108 | if not (uid==UID and pwd==PWD): 109 | print('Not authenticated') 110 | cs.close() 111 | continue 112 | # We are authenticated, so continue serving 113 | cs.write(b'%s\r\n\r\n' % hdr['stream']) 114 | pic=camera.capture 115 | put=cs.write 116 | hr=hdr['frame'] 117 | while True: 118 | # once connected and authenticated just send the jpg data 119 | # client use HTTP protocol (not RTSP) 120 | try: 121 | put(b'%s\r\n\r\n' % hr) 122 | put(pic()) 123 | put(b'\r\n') # send and flush the send buffer 124 | except Exception as e: 125 | print('TCP send error', e) 126 | cs.close() 127 | break 128 | else: 129 | if not con: 130 | print("WiFi not connected.") 131 | if not cam: 132 | print("Camera not ready. Please do machine.reset()") 133 | else: 134 | camera.deinit() 135 | print("System not ready. Please restart") 136 | 137 | print('System aborted') 138 | 139 | -------------------------------------------------------------------------------- /X23/esp32s3-freenove/scripts/streaming_server.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # run this on ESP32 Camera 26 | 27 | import esp 28 | # from bluetooth import BLE 29 | import network 30 | from time import sleep 31 | import socket as soc 32 | import camera 33 | import cam_config as cc 34 | from auth import AP, PW, UID, PWD 35 | 36 | hdr = { 37 | # live stream - 38 | # URL: /live 39 | 'stream': """HTTP/1.1 200 OK 40 | Content-Type: multipart/x-mixed-replace; boundary=kaki5 41 | Connection: keep-alive 42 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 43 | Expires: Thu, Jan 01 1970 00:00:00 GMT 44 | Pragma: no-cache""", 45 | # live stream - 46 | # URL: 47 | 'frame': """--kaki5 48 | Content-Type: image/jpeg"""} 49 | 50 | # esp.osdebug(None) # turn off debugging log. Uncomment to show debugging log 51 | 52 | # BLE().active(False) # disable ble 53 | 54 | # URL with the above UID and PWD, eg 55 | # http://192.168.4.74/free/Hi-Nove-La 56 | 57 | # default config is freenove 58 | cc.configure(camera, cc.freenove) # not really needed - default in firmware is freenove 59 | 60 | # both pixformat and framesize MUST before camera.init 61 | # after camera.init() you need to do camera.deinit() if you want to 62 | # change pixformat and or framesize, and camera.init() again. 63 | 64 | #camera.conf(cc.FRAMESIZE,cc.FRAMESIZE_SVGA) # good for webstreaming 65 | camera.conf(cc.FRAMESIZE,cc.FRAMESIZE_QVGA) # good for opencv 66 | cam = camera.init() 67 | print("Camera ready?: ", cam) 68 | 69 | # connect to access point 70 | network.WLAN(network.AP_IF).active(False) 71 | sta = network.WLAN(network.STA_IF) 72 | sta.active(True) 73 | 74 | con = () 75 | if not sta.isconnected(): 76 | sta.connect(AP, PW) # connect to AP with PW 77 | # wait for WiFi 78 | for i in range(5): 79 | if sta.isconnected(): con = sta.ifconfig(); break 80 | else: print("WIFI not ready. Wait...");sleep(2) 81 | else: 82 | con = sta.ifconfig() 83 | 84 | if con: 85 | print("WIFI ready") 86 | print(con) 87 | 88 | if con and cam: # WiFi and camera are ready 89 | if cam: 90 | # set preffered camera setting 91 | camera.contrast(2) # increase contrast 92 | camera.speffect(2) # jpeg grayscale 93 | if con: 94 | # TCP server 95 | port = 80 96 | addr = soc.getaddrinfo('0.0.0.0', port)[0][-1] 97 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 98 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 99 | s.bind(addr) 100 | s.listen(1) 101 | # s.settimeout(5.0) 102 | while True: # start HTTP-based streaming server 103 | cs, ca = s.accept() # wait for client connect 104 | print('Request from:', ca) 105 | w = cs.recv(200) # blocking 106 | (_, uid, pwd) = w.decode().split('\r\n')[0].split()[1].split('/') 107 | # print(_, uid, pwd) 108 | if not (uid==UID and pwd==PWD): 109 | print('Not authenticated') 110 | cs.close() 111 | continue 112 | # We are authenticated, so continue serving 113 | cs.write(b'%s\r\n\r\n' % hdr['stream']) 114 | pic=camera.capture 115 | put=cs.write 116 | hr=hdr['frame'] 117 | while True: 118 | # once connected and authenticated just send the jpg data 119 | # client use HTTP protocol (not RTSP) 120 | try: 121 | put(b'%s\r\n\r\n' % hr) 122 | put(pic()) 123 | put(b'\r\n') # send and flush the send buffer 124 | except Exception as e: 125 | print('TCP send error', e) 126 | cs.close() 127 | break 128 | else: 129 | if not con: 130 | print("WiFi not connected.") 131 | if not cam: 132 | print("Camera not ready. Please do machine.reset()") 133 | else: 134 | camera.deinit() 135 | print("System not ready. Please restart") 136 | 137 | print('System aborted') 138 | 139 | -------------------------------------------------------------------------------- /X23/esp32s3-lilygo/scripts/streaming_server.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # run this on ESP32 Camera 26 | 27 | import esp 28 | # from bluetooth import BLE 29 | import network 30 | from time import sleep 31 | import socket as soc 32 | import camera 33 | import cam_config as cc 34 | from auth import AP, PW, UID, PWD 35 | from pmu import cam_power_on 36 | 37 | hdr = { 38 | # live stream - 39 | # URL: /live 40 | 'stream': """HTTP/1.1 200 OK 41 | Content-Type: multipart/x-mixed-replace; boundary=kaki5 42 | Connection: keep-alive 43 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 44 | Expires: Thu, Jan 01 1970 00:00:00 GMT 45 | Pragma: no-cache""", 46 | # live stream - 47 | # URL: 48 | 'frame': """--kaki5 49 | Content-Type: image/jpeg"""} 50 | 51 | # esp.osdebug(None) # turn off debugging log. Uncomment to show debugging log 52 | 53 | # BLE().active(False) # disable ble 54 | 55 | # Switch on camera power controlled by AXP2101 56 | cam_power_on() 57 | 58 | # default config is xiao 59 | cc.configure(camera, cc.lilygo) # not really needed - default in firmware is lilygo 60 | 61 | # both pixformat and framesize MUST before camera.init 62 | # after camera.init() you need to do camera.deinit() if you want to 63 | # change pixformat and or framesize, and camera.init() again. 64 | 65 | #camera.conf(cc.FRAMESIZE,cc.FRAMESIZE_SVGA) # good for webstreaming 66 | camera.conf(cc.FRAMESIZE,cc.FRAMESIZE_QVGA) # good for opencv 67 | cam = camera.init() 68 | print("Camera ready?: ", cam) 69 | 70 | # connect to access point 71 | network.WLAN(network.AP_IF).active(False) 72 | sta = network.WLAN(network.STA_IF) 73 | sta.active(True) 74 | 75 | con = () 76 | if not sta.isconnected(): 77 | sta.connect(AP, PW) # connect to AP with PW 78 | # wait for WiFi 79 | for i in range(5): 80 | if sta.isconnected(): con = sta.ifconfig(); break 81 | else: print("WIFI not ready. Wait...");sleep(2) 82 | else: 83 | con = sta.ifconfig() 84 | 85 | if con: 86 | print("WIFI ready") 87 | print(con) 88 | 89 | if con and cam: # WiFi and camera are ready 90 | if cam: 91 | # set preffered camera setting 92 | camera.contrast(2) # increase contrast 93 | camera.speffect(2) # jpeg grayscale 94 | if con: 95 | # TCP server 96 | port = 80 97 | addr = soc.getaddrinfo('0.0.0.0', port)[0][-1] 98 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 99 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 100 | s.bind(addr) 101 | s.listen(1) 102 | # s.settimeout(5.0) 103 | while True: # start HTTP-based streaming server 104 | cs, ca = s.accept() # wait for client connect 105 | print('Request from:', ca) 106 | w = cs.recv(200) # blocking 107 | (_, uid, pwd) = w.decode().split('\r\n')[0].split()[1].split('/') 108 | # print(_, uid, pwd) 109 | if not (uid==UID and pwd==PWD): 110 | print('Not authenticated') 111 | cs.close() 112 | continue 113 | # We are authenticated, so continue serving 114 | cs.write(b'%s\r\n\r\n' % hdr['stream']) 115 | pic=camera.capture 116 | put=cs.write 117 | hr=hdr['frame'] 118 | while True: 119 | # once connected and authenticated just send the jpg data 120 | # client use HTTP protocol (not RTSP) 121 | try: 122 | put(b'%s\r\n\r\n' % hr) 123 | put(pic()) 124 | put(b'\r\n') # send and flush the send buffer 125 | except Exception as e: 126 | print('TCP send error', e) 127 | cs.close() 128 | break 129 | else: 130 | if not con: 131 | print("WiFi not connected.") 132 | if not cam: 133 | print("Camera not ready. Please do machine.reset()") 134 | else: 135 | camera.deinit() 136 | print("System not ready. Please restart") 137 | 138 | print('System aborted') 139 | 140 | -------------------------------------------------------------------------------- /webcam.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # webcam.py MVC - This is the controller C of MVC 26 | 27 | from machine import reset 28 | from time import sleep 29 | import usocket as soc 30 | import gc 31 | # 32 | import camera 33 | from wifi import Sta 34 | from help import Setting as cam_setting 35 | import site 36 | 37 | auth=site.auth 38 | pwd=site.pwd 39 | 40 | def clean_up(cs): 41 | cs.close() # flash buffer and close socket 42 | del cs 43 | gc.collect() 44 | 45 | def route(pm): 46 | cs,rq=pm 47 | pth='*NOP*' 48 | rqp = rq.split('/') 49 | rl=len(rqp) 50 | if rl==1: # '' 51 | pth='/';v=0 52 | elif rl==2: # '/', '/a' 53 | pth=f'/{rqp[1]}';v=0 54 | else: # '/a/v' '/a/v/w/....' 55 | pth=f'/{rqp[1]}' 56 | if rqp[1]=='login': 57 | v=rqp[2] 58 | else: 59 | try: 60 | v=int(rqp[2]) 61 | except: 62 | v=0 63 | pth='*ERR*' 64 | print('Not an integer value', rqp[2]) 65 | if pth in site.app: 66 | #print(pth, site.app[pth]) 67 | site.app[pth](cs,v) 68 | elif pth=='*NOP*': 69 | site.NOP(cs) 70 | else: 71 | site.ERR(cs) 72 | clean_up(cs) 73 | 74 | def server(pm): 75 | p=pm[0] 76 | ss=soc.socket(soc.AF_INET, soc.SOCK_STREAM) 77 | ss.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 78 | sa = ('0.0.0.0', p) 79 | ss.bind(sa) 80 | ss.listen(1) # serve 1 client at a time 81 | print("Start server", p) 82 | if auth.on: 83 | print(f"Try - http://{site.server}/login/{auth.pwd}") 84 | else: 85 | print(f"Try - http://{site.server}") 86 | while True: 87 | ms='';rq=[] 88 | try: 89 | cs, ca = ss.accept() 90 | except: 91 | pass 92 | else: 93 | r=b'';e='' 94 | try: 95 | r = cs.recv(1024) 96 | except Exception as e: 97 | print(f"EX:{e}") 98 | clean_up(cs) 99 | try: 100 | ms = r.decode() 101 | rq = ms.split(' ') 102 | except Exception as e: 103 | print(f"RQ:{ms} EX:{e}") 104 | clean_up(cs) 105 | else: 106 | if len(rq)>=2: 107 | print(ca, rq[:2]) 108 | rv,ph=rq[:2] # GET /path 109 | if not auth.on: 110 | route((cs, ph)) 111 | continue 112 | elif auth.ip==ca[0]: # authenticated client 113 | route((cs, ph)) 114 | continue 115 | elif ph.find('login/')>=0: # do login 116 | site.client=ca[0] 117 | route((cs, ph)) 118 | continue 119 | else: 120 | # Unauthorized otherwise 121 | site.NO(cs) 122 | clean_up(cs) 123 | 124 | # wait for camera ready 125 | for i in range(5): 126 | cam = camera.init() 127 | print("Camera ready?: ", cam) 128 | if cam: break 129 | else: sleep(2) 130 | else: 131 | print('Timeout') 132 | reset() 133 | 134 | if cam: 135 | print("Camera ready") 136 | # wait for wifi ready 137 | w = Sta() 138 | w.connect() 139 | w.wait() 140 | for i in range(5): 141 | if w.wlan.isconnected(): break 142 | else: print("WIFI not ready. Wait...");sleep(2) 143 | else: 144 | print("WIFI not ready. Can't continue!") 145 | reset() 146 | 147 | # set auth 148 | auth.on=True 149 | #auth.on=False # False: no authentication needed 150 | 151 | if auth.on: 152 | auth.pwd=pwd() 153 | auth.ip='' 154 | print(f'PWD: {auth.pwd}') 155 | 156 | # set preffered camera setting 157 | camera.framesize(10) # frame size 800X600 (1.33 espect ratio) 158 | camera.contrast(2) # increase contrast 159 | camera.speffect(2) # jpeg grayscale 160 | 161 | cam_setting['framesize']=10 162 | cam_setting['contrast']=2 163 | cam_setting['speffect']=2 164 | 165 | site.ip=w.wlan.ifconfig()[0] 166 | site.camera=camera 167 | 168 | server((80,)) # port 80 169 | reset() 170 | 171 | 172 | -------------------------------------------------------------------------------- /help.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | Setting = { 26 | 'pixformat':0, # 0:JPEG, 1:Grayscale (2bytes/pixel), 2:RGB565 27 | 'framesize':11, # 1:96x96, 2:160x120, 3:176x144, 4:240x176, 5:240x240 28 | # 6:320x240, 7:400x296, 8:480x320, 9:640x480, 10:800x600 29 | # 11:1024x768, 12:1280x720, 13:1280x1024, 14:1600x1200 30 | # 15:1920x1080, 16:720x1280, 17:864x1536, 18:2048x1536 31 | 32 | 'quality':11, # [0,63] lower number means higher quality 33 | 'contrast':0, # [-2,2] higher number higher contrast 34 | 'saturation':0, # [-2,2] higher number higher saturation. -2 grayscale 35 | 'brightness':0, # [-2,2] higher number higher brightness. 2 brightest 36 | 'speffect':0, # 0:,no effect 1:negative, 2:black and white, 3:reddish, 37 | # 4:greenish, 5:blue, 6:retro 38 | 39 | 'whitebalance':0, # 0:default, 1:sunny, 2:cloudy, 3:office, 4:home 40 | 'aelevels':0, # [-2,2] AE Level: Automatic exposure 41 | 'aecvalue':0, # [0,1200] AEC Value: Automatic exposure control 42 | 'agcgain':0, # [0,30] AGC Gain: Automatic Gain Control 43 | } 44 | 45 | def help(server): 46 | c=Setting 47 | return f""" 48 | Autentication: 49 | Login to server with a one-time password. 50 | http://{server}/login/ 51 | After login, only the authenticated client can connect to server. 52 | 53 | Logout from server. 54 | http://{server}/logout 55 | The client is no longer authenticated. Create new one-time password. 56 | The password is shown in REPL. 57 | Any web browser can now login using the password. 58 | 59 | NB! The server is open to all if auth.on=False 60 | 61 | Help: 62 | Show this page 63 | http://{server} 64 | If auth.on=True then you need to login first. 65 | 66 | Streaming: 67 | Webcam live streaming 68 | http://{server}/webcam 69 | To stop streaming just go to other URL e.g. http://{server}/snap 70 | 71 | Still photo: 72 | Take picture 73 | http://{server}/snap 74 | 75 | Take picture with LED flash 76 | http://{server}/blitz 77 | 78 | HTML image view port rotation: 79 | Rotate the with transform:rotate() in style defination. 80 | http://{server}/rot/n 81 | n is one these value [0,90,180,270,360]. You can display the 82 | image/video taken by the camera in portrait or landscape mode by 83 | rotating the image view port. Depending on your camera sensor and 84 | the orientation of your board, http://{server}/rot/90 may show 85 | portrait mode image on your browser. 86 | 87 | Camera setting: 88 | pixformat - http://{server}/fmt/n 89 | framesize - http://{server}/pix/n 90 | quality - http://{server}/qua/n 91 | contrast - http://{server}/con/n 92 | saturation - http://{server}/sat/n 93 | brightness - http://{server}/bri/n 94 | speffect - http://{server}/spe/n 95 | whitebalance - http://{server}/wbl/n 96 | aelevels - http://{server}/ael/n 97 | aecvalue - http://{server}/aec/n 98 | agcgain - http://{server}/agc/n 99 | 100 | NB! n is integer value (can be negative). 101 | See listing below for appropriate value for each setting. 102 | 103 | Camera current setting: 104 | pixformat={c['pixformat']} # 0:JPEG, 1:Grayscale (2bytes/pixel), 2:RGB565 105 | framesize={c['framesize']} # 1:96x96, 2:160x120, 3:176x144, 4:240x176, 5:240x240 106 | # 6:320x240, 7:400x296, 8:480x320, 9:640x480, 10:800x600 107 | # 11:1024x768, 12:1280x720, 13:1280x1024, 14:1600x1200 108 | # 15:1920x1080, 16:720x1280, 17:864x1536, 18:2048x1536 109 | quality={c['quality']} # [10,63] lower number means higher quality 110 | contrast={c['contrast']} # [-2,2] higher number higher contrast 111 | saturation={c['saturation']} # [-2,2] higher number higher saturation. -2 grayscale 112 | brightness={c['brightness']} # [-2,2] higher number higher brightness. 2 brightest 113 | speffect={c['speffect']} # 0:,no effect 1:negative, 2:black and white, 3:reddish, 114 | # 4:greenish, 5:blue, 6:retro 115 | whitebalance={c['whitebalance']} # 0:default, 1:sunny, 2:cloudy, 3:office, 4:home 116 | aelevels={c['aelevels']} # [-2,2] AE Level: Automatic exposure 117 | aecvalue={c['aecvalue']} # [0,1200] AEC Value: Automatic exposure control 118 | agcgain={c['agcgain']} # [0,30] AGC Gain: Automatic Gain Control 119 | 120 | """ 121 | -------------------------------------------------------------------------------- /firmwares-20230717/Note.md: -------------------------------------------------------------------------------- 1 | **configuration**: 2 | 3 | | name | key | note | 4 | |-------------|-----------|------| 5 | | PIN_PWDN | 0 | Powerdown, -1 if not used 6 | | PIN_RESET | 1 | Reset, -1 if reset will be done by software 7 | | PIN_XCLK | 2 | Sensor clock input, -1 if external crystal is used 8 | | PIN_SIOD | 3 | SCCB serial interface data (I2C SDA) 9 | | PIN_SIOC | 4 | SCCB serial interface clock (I2C SCL) 10 | | PIN_D7 | 5 | Video port output Y9 (bit#7) 11 | | PIN_D6 | 6 | Video port output Y8 (bit#6) 12 | | PIN_D5 | 7 | Video port output Y7 (bit#5) 13 | | PIN_D4 | 8 | Video port output Y6 (bit#4) 14 | | PIN_D3 | 9 | Video port output Y5 (bit#3) 15 | | PIN_D2 | 10 | Video port output Y4 (bit#2) 16 | | PIN_D1 | 11 | Video port output Y3 (bit#1) 17 | | PIN_D0 | 12 | Video port output Y2 (bit#0) 18 | | PIN_VSYNC | 13 | Vertical synchronization output 19 | | PIN_HREF | 14 | Horizontal reference output 20 | | PIN_PCLK | 15 | Pixel clock output 21 | | XCLK_MHZ | 16 | Sensor clock speed (10, 20) 22 | | PIXFORMAT | 17 | See **pixformat** 23 | | FRAMESIZE | 18 | See **framesize** 24 | | JPEG_QUALITY| 19 | Jpeg quality (10, 63) 25 | | FB_COUNT | 20 | 1 (esp32 2MB PSRAM) or 2 (esp32s3 8MB PSRAM) 26 | 27 | **framesize**: 28 | 29 | | name | key | pixel | note | 30 | |-------------|-----|-------|-----| 31 | | FRAMESIZE_96X96 | 1 | 96x96 | Square | 32 | | FRAMESIZE_QQVGA | 2 | 160x120 | | 33 | | FRAMESIZE_QCIF | 3 | 176x144 | | 34 | | FRAMESIZE_HQVGA | 4 | 240x176 | | 35 | | FRAMESIZE_240X240 | 5 | 240x240 | Square | 36 | | FRAMESIZE_QVGA | 6 | 320x240 | | 37 | | FRAMESIZE_CIF | 7 | 400x296 | | 38 | | FRAMESIZE_HVGA | 8 | 480x320 | | 39 | | FRAMESIZE_VGA | 9 | 640x480 | | 40 | | FRAMESIZE_SVGA | 10 | 800x600 | default | 41 | | FRAMESIZE_XGA | 11 | 1024x768 | | 42 | | FRAMESIZE_HD | 12 | 1280x720 | | 43 | | FRAMESIZE_SXGA | 13 | 1280x1024 | | 44 | | FRAMESIZE_UXGA | 14 | 1600x1200 | | 45 | | FRAMESIZE_FHD | 15 | 1920x1080 | | 46 | | FRAMESIZE_P_HD | 16 | 720x1280 | | 47 | | FRAMESIZE_P_3MP | 17 | 864x1536 | | 48 | | FRAMESIZE_QXGA | 18 | 2048x1536 | | 49 | 50 | **pixformat**: 51 | 52 | | name | key | note | 53 | |-------------|-----------|------| 54 | | PIXFORMAT_RGB565 | 1 | 2BPP/RGB565 | 55 | | PIXFORMAT_YUV422 | 2 | 2BPP/YUV422 | 56 | | PIXFORMAT_YUV420 | 3 | 1.5BPP/YUV420 | 57 | | PIXFORMAT_GRAYSCALE | 4 | 1BPP/GRAYSCALE | 58 | | PIXFORMAT_JPEG | 5 | JPEG/COMPRESSED | 59 | | PIXFORMAT_RGB888 | 6 | 3BPP/RGB888 | 60 | | PIXFORMAT_RAW | 7 | RAW | 61 | | PIXFORMAT_RGB444 | 8 | 3BP2P/RGB444 | 62 | | PIXFORMAT_RGB555 | 9 | 3BP2P/RGB555 | 63 | 64 | camera methods (listed alfabatically): 65 | 66 | | name | parameter | note | 67 | |-------------|-----------|------| 68 | | aecvalue | [0, 1200] default 0 | Automatic Exposure Control | 69 | | | | Bigger value longer exposure | 70 | | aelevels | [-2, 2] default 0 | Automatic Exposure Level | 71 | | | | Bigger value brighter image | 72 | | agcgain | [0, 30] default 30 | Automatic Gain Control | 73 | | | | Lower value darker image, less artefact | 74 | | brightness | [-2, 2] default 0 | Brightness | 75 | | | | Bigger value brighter image | 76 | | capture | | Read sensor buffer into memory | 77 | | | | The image format and size depend on pixformat and framesize settings| 78 | | capture_bmp | | Convert sensor buffer to BMP and read into memory | 79 | | | | The size depends on framesize setting | 80 | | capture_jpg | | Convert sensor buffer to JPG and read into memory | 81 | | | | The size depends on framesize setting | 82 | | | | Convert only if pixformat is not JPEG | 83 | | conf | what, value | camera.conf(w,v) see **configuration** | 84 | | | | Configuration with camera.conf() must be done before camera.init() | 85 | | contrast | [-2, 2] default 0| Constrast, 2 highest constrast | 86 | | deinit | | Deinitialize camera sensor. Close and disconnect image sensor from the system| 87 | | flip | | Flip image vertically | 88 | | framesize | [1, 18] default 10 (SVGA) | See **framesize** | 89 | | init | | Initialize camera sensor. Open and connect image sensor to the system. The state persist across soft-reboot. Do camera.deinit() before a new camera.init() ( after change configuration for example) | 90 | | mirror | | Flip image horizontally | 91 | | pixformat | [1, 9] default 5 (JPEG) | See **pixformat** | 92 | | quality | [10, 63] default 12 | JPEG quality, highest quality at 10 | 93 | | saturation | [-2, 2] default 0 | Color saturation, -2 grayscale and 2 highest color saturation. 94 | | speffect | [0, 6] default 0 | Special effect: | 95 | | | | 1 - negative | 96 | | | | 2 - black and white | 97 | | | | 3 - reddish | 98 | | | | 4 - greenish | 99 | | | | 5 - blueish | 100 | | | | 6 - retro (brownish) | 101 | | whitebalance| [0, 4] default 0 | White balance: | 102 | | | | 1 - sunny | 103 | | | | 2 - cloudy | 104 | | | | 3 - office | 105 | | | | 4 - home | 106 | 107 | -------------------------------------------------------------------------------- /firmwares-20230717/scripts/help.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | Setting = { 26 | 'pixformat':5, # 1:RGB565, 2:YUV422, 3:YUV420, 4:GRAYSCALE, 5:COMPRESSED, 27 | # 6:RGB888, 7:RAW, 8:RGB444, 9:RGB555 28 | 'framesize':11, # 1:96x96, 2:160x120, 3:176x144, 4:240x176, 5:240x240 29 | # 6:320x240, 7:400x296, 8:480x320, 9:640x480, 10:800x600 30 | # 11:1024x768, 12:1280x720, 13:1280x1024, 14:1600x1200 31 | # 15:1920x1080, 16:720x1280, 17:864x1536, 18:2048x1536 32 | 33 | 'quality':11, # [0,63] lower number means higher quality 34 | 'contrast':0, # [-2,2] higher number higher contrast 35 | 'saturation':0, # [-2,2] higher number higher saturation. -2 grayscale 36 | 'brightness':0, # [-2,2] higher number higher brightness. 2 brightest 37 | 'speffect':0, # 0:,no effect 1:negative, 2:black and white, 3:reddish, 38 | # 4:greenish, 5:blue, 6:retro 39 | 40 | 'whitebalance':0, # 0:default, 1:sunny, 2:cloudy, 3:office, 4:home 41 | 'aelevels':0, # [-2,2] AE Level: Automatic exposure 42 | 'aecvalue':0, # [0,1200] AEC Value: Automatic exposure control 43 | 'agcgain':0, # [0,30] AGC Gain: Automatic Gain Control 44 | } 45 | 46 | def help(server): 47 | c=Setting 48 | return f""" 49 | Autentication: 50 | Login to server with a one-time password. 51 | http://{server}/login/ 52 | After login, only the authenticated client can connect to server. 53 | 54 | Logout from server. 55 | http://{server}/logout 56 | The client is no longer authenticated. Create new one-time password. 57 | The password is shown in REPL. 58 | Any web browser can now login using the password. 59 | 60 | NB! The server is open to all if auth.on=False 61 | 62 | Help: 63 | Show this page 64 | http://{server} 65 | If auth.on=True then you need to login first. 66 | 67 | Streaming: 68 | Webcam live streaming 69 | http://{server}/webcam 70 | To stop streaming just go to other URL e.g. http://{server}/snap 71 | 72 | Still photo: 73 | Take picture 74 | http://{server}/snap 75 | 76 | Take picture with LED flash 77 | http://{server}/blitz 78 | 79 | HTML image view port rotation: 80 | Rotate the with transform:rotate() in style defination. 81 | http://{server}/rot/n 82 | n is one these value [0,90,180,270,360]. You can display the 83 | image/video taken by the camera in portrait or landscape mode by 84 | rotating the image view port. Depending on your camera sensor and 85 | the orientation of your board, http://{server}/rot/90 may show 86 | portrait mode image on your browser. 87 | 88 | Camera setting: 89 | pixformat - http://{server}/fmt/n 90 | framesize - http://{server}/pix/n 91 | quality - http://{server}/qua/n 92 | contrast - http://{server}/con/n 93 | saturation - http://{server}/sat/n 94 | brightness - http://{server}/bri/n 95 | speffect - http://{server}/spe/n 96 | whitebalance - http://{server}/wbl/n 97 | aelevels - http://{server}/ael/n 98 | aecvalue - http://{server}/aec/n 99 | agcgain - http://{server}/agc/n 100 | 101 | NB! n is integer value (can be negative). 102 | See listing below for appropriate value for each setting. 103 | 104 | Camera current setting: 105 | pixformat={c['pixformat']} # 1:2BPP/RGB565, 2:2BPP/YUV422, 3:1.5BPP/YUV420, 106 | # 4:1BPP/GRAYSCALE, 5:JPEG/COMPRESSED, 6:3BPP/RGB888, 107 | # 7:RAW, 8:3BP2P/RGB444, 9:3BP2P/RGB555 108 | framesize={c['framesize']} # 1:96x96, 2:160x120, 3:176x144, 4:240x176, 5:240x240 109 | # 6:320x240, 7:400x296, 8:480x320, 9:640x480, 10:800x600 110 | # 11:1024x768, 12:1280x720, 13:1280x1024, 14:1600x1200 111 | # 15:1920x1080, 16:720x1280, 17:864x1536, 18:2048x1536 112 | quality={c['quality']} # [10,63] lower number means higher quality 113 | contrast={c['contrast']} # [-2,2] higher number higher contrast 114 | saturation={c['saturation']} # [-2,2] higher number higher saturation. -2 grayscale 115 | brightness={c['brightness']} # [-2,2] higher number higher brightness. 2 brightest 116 | speffect={c['speffect']} # 0:,no effect 1:negative, 2:black and white, 3:reddish, 117 | # 4:greenish, 5:blue, 6:retro 118 | whitebalance={c['whitebalance']} # 0:default, 1:sunny, 2:cloudy, 3:office, 4:home 119 | aelevels={c['aelevels']} # [-2,2] AE Level: Automatic exposure 120 | aecvalue={c['aecvalue']} # [0,1200] AEC Value: Automatic exposure control 121 | agcgain={c['agcgain']} # [0,30] AGC Gain: Automatic Gain Control 122 | 123 | """ 124 | 125 | -------------------------------------------------------------------------------- /firmwares-20230521/scripts/webcam.py: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # webcam.py MVC - This is the controller C of MVC 26 | 27 | from machine import reset 28 | from time import sleep 29 | import usocket as soc 30 | import gc 31 | # 32 | import camera 33 | import config as K 34 | from wifi import Sta 35 | from help import Setting as cam_setting 36 | import site 37 | 38 | gc.enable() # Enable automatic garbage collection 39 | 40 | auth=site.auth 41 | pwd=site.pwd 42 | 43 | def clean_up(cs): 44 | cs.close() # flash buffer and close socket 45 | del cs 46 | # gc.collect() 47 | 48 | def route(pm): 49 | cs,rq=pm 50 | pth='*NOP*' 51 | rqp = rq.split('/') 52 | rl=len(rqp) 53 | if rl==1: # '' 54 | pth='/';v=0 55 | elif rl==2: # '/', '/a' 56 | pth=f'/{rqp[1]}';v=0 57 | else: # '/a/v' '/a/v/w/....' 58 | pth=f'/{rqp[1]}' 59 | if rqp[1]=='login': 60 | v=rqp[2] 61 | else: 62 | try: 63 | v=int(rqp[2]) 64 | except: 65 | v=0 66 | pth='*ERR*' 67 | print('Not an integer value', rqp[2]) 68 | if pth in site.app: 69 | #print(pth, site.app[pth]) 70 | site.app[pth](cs,v) 71 | elif pth=='*NOP*': 72 | site.NOP(cs) 73 | else: 74 | site.ERR(cs) 75 | clean_up(cs) 76 | 77 | def server(pm): 78 | p=pm[0] 79 | ss=soc.socket(soc.AF_INET, soc.SOCK_STREAM) 80 | ss.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 81 | sa = ('0.0.0.0', p) 82 | ss.bind(sa) 83 | ss.listen(1) # serve 1 client at a time 84 | print("Start server", p) 85 | if auth.on: 86 | print(f"Try - http://{site.server}/login/{auth.pwd}") 87 | else: 88 | print(f"Try - http://{site.server}") 89 | while True: 90 | ms='';rq=[] 91 | try: 92 | cs, ca = ss.accept() 93 | except: 94 | pass 95 | else: 96 | r=b'';e='' 97 | try: 98 | r = cs.recv(1024) 99 | except Exception as e: 100 | print(f"EX:{e}") 101 | clean_up(cs) 102 | try: 103 | ms = r.decode() 104 | rq = ms.split(' ') 105 | except Exception as e: 106 | print(f"RQ:{ms} EX:{e}") 107 | clean_up(cs) 108 | else: 109 | if len(rq)>=2: 110 | print(ca, rq[:2]) 111 | rv,ph=rq[:2] # GET /path 112 | if not auth.on: 113 | route((cs, ph)) 114 | continue 115 | elif auth.ip==ca[0]: # authenticated client 116 | route((cs, ph)) 117 | continue 118 | elif ph.find('login/')>=0: # do login 119 | site.client=ca[0] 120 | route((cs, ph)) 121 | continue 122 | else: 123 | # Unauthorized otherwise 124 | site.NO(cs) 125 | clean_up(cs) 126 | 127 | # set camera configuration 128 | K.configure(camera, K.ai_thinker) # AI-Thinker PINs map - no need (default) 129 | #camera.conf(K.XCLK_MHZ, 16) # 16Mhz xclk rate 130 | camera.conf(K.XCLK_MHZ, 14) # 14Mhz xclk rate 131 | #camera.conf(K.XCLK_MHZ, 13) # 14Mhz xclk rate 132 | #camera.conf(K.XCLK_MHZ, 12) # 12Mhz xclk rate - to reduce "cam_hal: EV-EOF-OVF" 133 | 134 | # wait for camera ready 135 | for i in range(5): 136 | cam = camera.init() 137 | print("Camera ready?: ", cam) 138 | if cam: break 139 | else: sleep(2) 140 | else: 141 | print('Timeout') 142 | reset() 143 | 144 | if cam: 145 | print("Camera ready") 146 | # wait for wifi ready 147 | w = Sta() 148 | w.connect() 149 | w.wait() 150 | for i in range(5): 151 | if w.wlan.isconnected(): break 152 | else: print("WIFI not ready. Wait...");sleep(2) 153 | else: 154 | print("WIFI not ready. Can't continue!") 155 | reset() 156 | 157 | # set auth 158 | auth.on=True 159 | #auth.on=False # False: no authentication needed 160 | 161 | if auth.on: 162 | auth.pwd=pwd() 163 | auth.ip='' 164 | print(f'PWD: {auth.pwd}') 165 | 166 | # set preffered camera setting 167 | camera.framesize(10) # frame size 800X600 (1.33 espect ratio) 168 | #camera.framesize(11) 169 | #camera.framesize(12) 170 | camera.quality(5) 171 | #camera.quality(10) 172 | camera.brightness(3) 173 | camera.contrast(2) # increase contrast 174 | #camera.contrast(0) 175 | camera.speffect(2) # jpeg grayscale 176 | 177 | cam_setting['framesize']=10 178 | cam_setting['quality']=5 179 | cam_setting['contrast']=0 180 | cam_setting['speffect']=2 181 | cam_setting['brightness']=3 182 | 183 | site.ip=w.wlan.ifconfig()[0] 184 | site.camera=camera 185 | 186 | server((80,)) # port 80 187 | reset() 188 | 189 | 190 | -------------------------------------------------------------------------------- /firmwares-20230717/scripts/webcam.py: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # webcam.py MVC - This is the controller C of MVC 26 | 27 | from machine import reset 28 | from time import sleep 29 | import usocket as soc 30 | import gc 31 | # 32 | import camera 33 | import config as K 34 | from wifi import Sta 35 | from help import Setting as cam_setting 36 | import site 37 | 38 | gc.enable() # Enable automatic garbage collection 39 | 40 | auth=site.auth 41 | pwd=site.pwd 42 | 43 | def clean_up(cs): 44 | cs.close() # flash buffer and close socket 45 | del cs 46 | # gc.collect() 47 | 48 | def route(pm): 49 | cs,rq=pm 50 | pth='*NOP*' 51 | rqp = rq.split('/') 52 | rl=len(rqp) 53 | if rl==1: # '' 54 | pth='/';v=0 55 | elif rl==2: # '/', '/a' 56 | pth=f'/{rqp[1]}';v=0 57 | else: # '/a/v' '/a/v/w/....' 58 | pth=f'/{rqp[1]}' 59 | if rqp[1]=='login': 60 | v=rqp[2] 61 | else: 62 | try: 63 | v=int(rqp[2]) 64 | except: 65 | v=0 66 | pth='*ERR*' 67 | print('Not an integer value', rqp[2]) 68 | if pth in site.app: 69 | #print(pth, site.app[pth]) 70 | site.app[pth](cs,v) 71 | elif pth=='*NOP*': 72 | site.NOP(cs) 73 | else: 74 | site.ERR(cs) 75 | clean_up(cs) 76 | 77 | def server(pm): 78 | p=pm[0] 79 | ss=soc.socket(soc.AF_INET, soc.SOCK_STREAM) 80 | ss.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 81 | sa = ('0.0.0.0', p) 82 | ss.bind(sa) 83 | ss.listen(1) # serve 1 client at a time 84 | print("Start server", p) 85 | if auth.on: 86 | print(f"Try - http://{site.server}/login/{auth.pwd}") 87 | else: 88 | print(f"Try - http://{site.server}") 89 | while True: 90 | ms='';rq=[] 91 | try: 92 | cs, ca = ss.accept() 93 | except: 94 | pass 95 | else: 96 | r=b'';e='' 97 | try: 98 | r = cs.recv(1024) 99 | except Exception as e: 100 | print(f"EX:{e}") 101 | clean_up(cs) 102 | try: 103 | ms = r.decode() 104 | rq = ms.split(' ') 105 | except Exception as e: 106 | print(f"RQ:{ms} EX:{e}") 107 | clean_up(cs) 108 | else: 109 | if len(rq)>=2: 110 | print(ca, rq[:2]) 111 | rv,ph=rq[:2] # GET /path 112 | if not auth.on: 113 | route((cs, ph)) 114 | continue 115 | elif auth.ip==ca[0]: # authenticated client 116 | route((cs, ph)) 117 | continue 118 | elif ph.find('login/')>=0: # do login 119 | site.client=ca[0] 120 | route((cs, ph)) 121 | continue 122 | else: 123 | # Unauthorized otherwise 124 | site.NO(cs) 125 | clean_up(cs) 126 | 127 | # set camera configuration 128 | K.configure(camera, K.ai_thinker) # AI-Thinker PINs map - no need (default) 129 | #camera.conf(K.XCLK_MHZ, 16) # 16Mhz xclk rate 130 | camera.conf(K.XCLK_MHZ, 14) # 14Mhz xclk rate 131 | #camera.conf(K.XCLK_MHZ, 13) # 14Mhz xclk rate 132 | #camera.conf(K.XCLK_MHZ, 12) # 12Mhz xclk rate - to reduce "cam_hal: EV-EOF-OVF" 133 | 134 | # wait for camera ready 135 | for i in range(5): 136 | cam = camera.init() 137 | print("Camera ready?: ", cam) 138 | if cam: break 139 | else: sleep(2) 140 | else: 141 | print('Timeout') 142 | reset() 143 | 144 | if cam: 145 | print("Camera ready") 146 | # wait for wifi ready 147 | w = Sta() 148 | w.connect() 149 | w.wait() 150 | for i in range(5): 151 | if w.wlan.isconnected(): break 152 | else: print("WIFI not ready. Wait...");sleep(2) 153 | else: 154 | print("WIFI not ready. Can't continue!") 155 | reset() 156 | 157 | # set auth 158 | auth.on=True 159 | #auth.on=False # False: no authentication needed 160 | 161 | if auth.on: 162 | auth.pwd=pwd() 163 | auth.ip='' 164 | print(f'PWD: {auth.pwd}') 165 | 166 | # set preffered camera setting 167 | camera.framesize(10) # frame size 800X600 (1.33 espect ratio) 168 | #camera.framesize(11) 169 | #camera.framesize(12) 170 | camera.quality(5) 171 | #camera.quality(10) 172 | camera.brightness(3) 173 | camera.contrast(2) # increase contrast 174 | #camera.contrast(0) 175 | camera.speffect(2) # jpeg grayscale 176 | 177 | cam_setting['framesize']=10 178 | cam_setting['quality']=5 179 | cam_setting['contrast']=0 180 | cam_setting['speffect']=2 181 | cam_setting['brightness']=3 182 | 183 | site.ip=w.wlan.ifconfig()[0] 184 | site.camera=camera 185 | 186 | server((80,)) # port 80 187 | reset() 188 | 189 | 190 | -------------------------------------------------------------------------------- /Christmas-2023-Edition/scripts/cam_config.py: -------------------------------------------------------------------------------- 1 | from micropython import const 2 | 3 | #-camera configuration int keys ** DONT EDIT **--------------- 4 | PIN_PWDN = const(0) # power-down 5 | PIN_RESET = const(1) # reset 6 | PIN_XCLK = const(2) 7 | PIN_SIOD = const(3) # SDA 8 | PIN_SIOC = const(4) # SCL 9 | 10 | PIN_D7 = const(5) 11 | PIN_D6 = const(6) 12 | PIN_D5 = const(7) 13 | PIN_D4 = const(8) 14 | PIN_D3 = const(9) 15 | PIN_D2 = const(10) 16 | PIN_D1 = const(11) 17 | PIN_D0 = const(12) 18 | PIN_VSYNC = const(13) 19 | PIN_HREF = const(14) 20 | PIN_PCLK = const(15) 21 | 22 | XCLK_MHZ = const(16) # camera machine clock 23 | PIXFORMAT = const(17) # pixel format 24 | FRAMESIZE = const(18) # framesize 25 | JPEG_QUALITY= const(19) 26 | FB_COUNT = const(20) # framebuffer count > 1 continuous mode (JPEG only) 27 | 28 | PIXFORMAT_RGB565 = const(1) # 2BPP/RGB565 29 | PIXFORMAT_YUV422 = const(2) # 2BPP/YUV422 30 | PIXFORMAT_YUV420 = const(3) # 1.5BPP/YUV420 31 | PIXFORMAT_GRAYSCALE = const(4) # 1BPP/GRAYSCALE 32 | PIXFORMAT_JPEG = const(5) # JPEG/COMPRESSED 33 | PIXFORMAT_RGB888 = const(6) # 3BPP/RGB888 34 | PIXFORMAT_RAW = const(7) # RAW 35 | PIXFORMAT_RGB444 = const(8) # 3BP2P/RGB444 36 | PIXFORMAT_RGB555 = const(9) # 3BP2P/RGB555 37 | 38 | FRAMESIZE_96X96 = const(1) # 96x96 (width x height) 39 | FRAMESIZE_QQVGA = const(2) # 160x120 40 | FRAMESIZE_QCIF = const(3) # 176x144 41 | FRAMESIZE_HQVGA = const(4) # 240x176 42 | FRAMESIZE_240X240 = const(5) # 240x240 43 | FRAMESIZE_QVGA = const(6) # 320x240 44 | FRAMESIZE_CIF = const(7) # 400x296 45 | FRAMESIZE_HVGA = const(8) # 480x320 46 | FRAMESIZE_VGA = const(9) # 640x480 47 | FRAMESIZE_SVGA = const(10) # 800x600 48 | FRAMESIZE_XGA = const(11) # 1024x768 49 | FRAMESIZE_HD = const(12) # 1280x720 50 | FRAMESIZE_SXGA = const(13) # 1280x1024 51 | FRAMESIZE_UXGA = const(14) # 1600x1200 52 | FRAMESIZE_FHD = const(15) # 1920x1080 53 | FRAMESIZE_P_HD = const(16) # 720x1280 54 | FRAMESIZE_P_3MP = const(17) # 864x1536 55 | FRAMESIZE_QXGA = const(18) # 2048x1536 56 | 57 | #------------------------------------------------------------- 58 | 59 | # OV2640 Boards configuration below (can edit - add your board) 60 | 61 | # AI-Thinker esp32-cam board 62 | ai_thinker = {PIN_PWDN:32, 63 | PIN_RESET:-1, 64 | PIN_XCLK:0, 65 | PIN_SIOD:26, 66 | PIN_SIOC:27, 67 | PIN_D7:35, 68 | PIN_D6:34, 69 | PIN_D5:39, 70 | PIN_D4:36, 71 | PIN_D3:21, 72 | PIN_D2:19, 73 | PIN_D1:18, 74 | PIN_D0:5, 75 | PIN_VSYNC:25, 76 | PIN_HREF:23, 77 | PIN_PCLK:22, 78 | XCLK_MHZ:16, 79 | PIXFORMAT:5, 80 | FRAMESIZE:10, 81 | JPEG_QUALITY:10, 82 | FB_COUNT:1, 83 | } 84 | 85 | # New 2022 esp32vrover dev 86 | esp_eye = {PIN_PWDN:-1, 87 | PIN_RESET:-1, 88 | PIN_XCLK:4, 89 | PIN_SIOD:18, 90 | PIN_SIOC:23, 91 | PIN_D7:36, 92 | PIN_D6:37, 93 | PIN_D5:38, 94 | PIN_D4:39, 95 | PIN_D3:35, 96 | PIN_D2:14, 97 | PIN_D1:13, 98 | PIN_D0:34, 99 | PIN_VSYNC:5, 100 | PIN_HREF:27, 101 | PIN_PCLK:25, 102 | XCLK_MHZ:16, 103 | PIXFORMAT:5, 104 | FRAMESIZE:10, 105 | JPEG_QUALITY:10, 106 | FB_COUNT:1, 107 | } 108 | 109 | # esp32 wrover dev 110 | wrover_dev = {PIN_PWDN:32, 111 | PIN_RESET:-1, 112 | PIN_XCLK:21, 113 | PIN_SIOD:26, 114 | PIN_SIOC:27, 115 | PIN_D7:35, 116 | PIN_D6:34, 117 | PIN_D5:39, 118 | PIN_D4:36, 119 | PIN_D3:19, 120 | PIN_D2:18, 121 | PIN_D1:5, 122 | PIN_D0:4, 123 | PIN_VSYNC:25, 124 | PIN_HREF:23, 125 | PIN_PCLK:22, 126 | XCLK_MHZ:12, 127 | PIXFORMAT:5, 128 | FRAMESIZE:10, 129 | JPEG_QUALITY:10, 130 | FB_COUNT:1, 131 | } 132 | 133 | # Test 134 | wrover_test = {PIN_PWDN:-1, 135 | PIN_RESET:-1, 136 | PIN_XCLK:21, 137 | PIN_SIOD:26, 138 | PIN_SIOC:27, 139 | PIN_D7:35, 140 | PIN_D6:34, 141 | PIN_D5:39, 142 | PIN_D4:36, 143 | PIN_D3:19, 144 | PIN_D2:18, 145 | PIN_D1:5, 146 | PIN_D0:4, 147 | PIN_VSYNC:25, 148 | PIN_HREF:23, 149 | PIN_PCLK:22, 150 | XCLK_MHZ:12, 151 | PIXFORMAT:5, 152 | FRAMESIZE:10, 153 | JPEG_QUALITY:10, 154 | FB_COUNT:1, 155 | } 156 | 157 | # Red Board (has internal clock for camera set at 12Mhz) 158 | red_board = {PIN_PWDN:32, # 159 | PIN_RESET:-1, 160 | PIN_XCLK:-1, # internal sensor clock 161 | PIN_SIOD:26, 162 | PIN_SIOC:27, 163 | PIN_D7:35, 164 | PIN_D6:34, 165 | PIN_D5:39, 166 | PIN_D4:36, 167 | PIN_D3:21, 168 | PIN_D2:19, 169 | PIN_D1:18, 170 | PIN_D0:5, 171 | PIN_VSYNC:25, 172 | PIN_HREF:23, 173 | PIN_PCLK:22, 174 | XCLK_MHZ:12, # the board has 12Mhz intrenal clock (MUST set to 12) 175 | PIXFORMAT:5, 176 | FRAMESIZE:10, 177 | JPEG_QUALITY:10, 178 | FB_COUNT:1, 179 | } 180 | 181 | def configure(cam, config): 182 | for key, val in config.items(): 183 | # print(key, val) 184 | cam.conf(key, val) 185 | 186 | -------------------------------------------------------------------------------- /site.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # site.py MVC - This is the model M of MVC 26 | 27 | from uos import urandom as ran 28 | from machine import Pin 29 | from html import pg, hdr 30 | from help import Setting as cam 31 | from help import help 32 | 33 | # Init global variables 34 | rot='0' 35 | flash_light=Pin(04,Pin.OUT) 36 | 37 | class auth: pass 38 | 39 | server='' 40 | client='' 41 | 42 | def pwd(size=8): 43 | alfa = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890' 44 | return ''.join([alfa[x] for x in [(ran(1)[0] % len(alfa)) for _ in range(size)]]) 45 | 46 | # These will be set by server script as site.ip and site.camera 47 | ip='' 48 | camera=None 49 | 50 | app={} 51 | def route(p): 52 | def w(g): 53 | app[p]=g 54 | return w 55 | 56 | def OK(cs): 57 | p=pg['OK'] 58 | ln=len(p)+2 59 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['OK']%ln, p)) 60 | 61 | def ERR(cs): 62 | p=pg['err'] 63 | ln=len(p)+2 64 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['err']%ln, p)) 65 | 66 | def NO(cs): 67 | p=pg['no'] 68 | ln=len(p)+2 69 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['err']%ln, p)) 70 | 71 | def NOP(cs): 72 | p=pg['none'] 73 | ln=len(p)+2 74 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['none']%ln, p)) 75 | 76 | def setting(cs,w,ok,cmd,v): 77 | #print("setting:", w, ok) 78 | if ok: 79 | cmd(w); cam[v]=w 80 | OK(cs) 81 | else: 82 | ERR(cs) 83 | 84 | @route('/') 85 | def root(cs,v): 86 | p=help(server) 87 | ln=len(p)+2 88 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['OK']%ln, p)) 89 | OK(cs) 90 | 91 | @route('/login') 92 | def login(cs,v): 93 | if auth.on: 94 | if auth.ip=='': 95 | if v==auth.pwd: 96 | auth.ip=client 97 | OK(cs) 98 | 99 | @route('/logout') 100 | def logout(cs,v): 101 | if auth.on: 102 | auth.pwd=pwd() 103 | auth.ip='' 104 | print(f'New PWD: {auth.pwd}') 105 | OK(cs) 106 | 107 | @route('/favicon.ico') 108 | def fav(cs,v): 109 | p=pg['favicon'] 110 | ln=len(p)+2 111 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['favicon']%ln, p)) 112 | 113 | @route('/webcam') 114 | def webcam(cs,v): 115 | global ip,rot 116 | p=pg['foto']%(f'http://{ip}/live',rot) # needed by opera, vivaldi, midori.. 117 | ln=len(p)+2 118 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['foto']%ln, p)) 119 | 120 | @route('/live') 121 | def live(cs,v): # live stream 122 | cs.write(b'%s\r\n\r\n' % hdr['stream']) 123 | cs.setblocking(True) 124 | pic=camera.capture 125 | put=cs.write 126 | hr=hdr['frame'] 127 | while True: 128 | try: 129 | put(b'%s\r\n\r\n' % hr) 130 | put(pic()) 131 | put(b'\r\n') # send and flush the send buffer 132 | except Exception as e: 133 | print(e) 134 | break 135 | 136 | @route('/snap') 137 | def snap(cs,v): 138 | global ip,rot 139 | p=pg['foto']%(f'http://{ip}/foto',rot) 140 | ln=len(p)+2 141 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['foto']%ln, p)) 142 | 143 | @route('/blitz') 144 | def blitz(cs,v): 145 | global ip,rot 146 | p=pg['foto']%(f'http://{ip}/boto',rot) 147 | ln=len(p)+2 148 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['foto']%ln, p)) 149 | 150 | @route('/foto') 151 | def foto(cs,v): # still photo 152 | #buf=camera.capture() 153 | #ln=len(buf) 154 | cs.setblocking(True) 155 | cs.write(b'%s\r\n\r\n' % hdr['pic']) 156 | cs.write(camera.capture()) 157 | cs.write(b'\r\n') # send and flush the send buffer 158 | #nc=cs.write(b'%s\r\n\r\n' % (hdr['pix']%ln)+buf) 159 | 160 | @route('/boto') 161 | def boto(cs,v): # still photo blitz on 162 | #buf=camera.capture() 163 | #ln=len(buf) 164 | cs.setblocking(True) 165 | cs.write(b'%s\r\n\r\n' % hdr['pic']) 166 | flash_light.on() 167 | cs.write(camera.capture()) 168 | flash_light.off() 169 | cs.write(b'\r\n') 170 | #nc=cs.write(b'%s\r\n\r\n' % (hdr['pix']%ln)+buf) 171 | 172 | @route('/rot') 173 | def rotate(cs,v): 174 | global rot 175 | rot=v 176 | OK(cs) 177 | 178 | @route('/flash') 179 | def flash(cs,v): 180 | if v==1: flash_light.on() 181 | else: flash_light.off() 182 | OK(cs) 183 | 184 | @route('/fmt') 185 | def fmt(cs,w): 186 | setting(cs,w,(w>=0 and w<=2),camera.pixformat,'pixformat') 187 | 188 | @route('/pix') 189 | def pix(cs,w): 190 | setting(cs,w,(w>0 and w<18),camera.framesize,'framesize') 191 | 192 | @route('/qua') 193 | def qua(cs,w): 194 | setting(cs,w,(w>9 and w<64),camera.quality,'quality') 195 | 196 | @route('/con') 197 | def con(cs,w): 198 | setting(cs,w,(w>-3 and w<3),camera.contrast,'contrast') 199 | 200 | @route('/sat') 201 | def sat(cs,w): 202 | setting(cs,w,(w>-3 and w<3),camera.saturation,'saturation') 203 | 204 | @route('/bri') 205 | def bri(cs,w): 206 | setting(cs,w,(w>-3 and w<3),camera.brightness,'brightness') 207 | 208 | @route('/ael') 209 | def ael(cs,w): 210 | setting(cs,w,(w>-3 and w<3),camera.aelevels,'aelevels') 211 | 212 | @route('/aec') 213 | def aec(cs,w): 214 | setting(cs,w,(w>=0 and w<=1200),camera.aecvalue,'aecvalue') 215 | 216 | @route('/agc') 217 | def agc(cs,w): 218 | setting(cs,w,(w>=0 and w<=30),camera.agcgain,'agcgain') 219 | 220 | @route('/spe') 221 | def spe(cs,w): 222 | setting(cs,w,(w>=0 and w<7),camera.speffect,'speffect') 223 | 224 | @route('/wbl') 225 | def wbl(cs,w): 226 | setting(cs,w,(w>=0 and w<5),camera.whitebalance,'whitebalance') 227 | 228 | -------------------------------------------------------------------------------- /firmwares-20230717/scripts/site.py: -------------------------------------------------------------------------------- 1 | 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) Sharil Tumin 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | #----------------------------------------------------------------------------- 24 | 25 | # site.py MVC - This is the model M of MVC 26 | 27 | from uos import urandom as ran 28 | from machine import Pin 29 | from html import pg, hdr 30 | from help import Setting as cam 31 | from help import help 32 | 33 | # Init global variables 34 | rot='0' 35 | flash_light=Pin(04,Pin.OUT) 36 | 37 | class auth: pass 38 | 39 | server='' 40 | client='' 41 | 42 | def pwd(size=8): 43 | alfa = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890' 44 | return ''.join([alfa[x] for x in [(ran(1)[0] % len(alfa)) for _ in range(size)]]) 45 | 46 | # These will be set by server script as site.ip and site.camera 47 | ip='' 48 | camera=None 49 | 50 | app={} 51 | def route(p): 52 | def w(g): 53 | app[p]=g 54 | return w 55 | 56 | def OK(cs): 57 | p=pg['OK'] 58 | ln=len(p)+2 59 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['OK']%ln, p)) 60 | 61 | def ERR(cs): 62 | p=pg['err'] 63 | ln=len(p)+2 64 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['err']%ln, p)) 65 | 66 | def NO(cs): 67 | p=pg['no'] 68 | ln=len(p)+2 69 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['err']%ln, p)) 70 | 71 | def NOP(cs): 72 | p=pg['none'] 73 | ln=len(p)+2 74 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['none']%ln, p)) 75 | 76 | def setting(cs,w,ok,cmd,v): 77 | #print("setting:", w, ok) 78 | if ok: 79 | cmd(w); cam[v]=w 80 | OK(cs) 81 | else: 82 | ERR(cs) 83 | 84 | @route('/') 85 | def root(cs,v): 86 | p=help(server) 87 | ln=len(p)+2 88 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['OK']%ln, p)) 89 | OK(cs) 90 | 91 | @route('/login') 92 | def login(cs,v): 93 | if auth.on: 94 | if auth.ip=='': 95 | if v==auth.pwd: 96 | auth.ip=client 97 | OK(cs) 98 | 99 | @route('/logout') 100 | def logout(cs,v): 101 | if auth.on: 102 | auth.pwd=pwd() 103 | auth.ip='' 104 | print(f'New PWD: {auth.pwd}') 105 | OK(cs) 106 | 107 | @route('/favicon.ico') 108 | def fav(cs,v): 109 | p=pg['favicon'] 110 | ln=len(p)+2 111 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['favicon']%ln, p)) 112 | 113 | @route('/webcam') 114 | def webcam(cs,v): 115 | global ip,rot 116 | p=pg['foto']%(f'http://{ip}/live',rot) # needed by opera, vivaldi, midori.. 117 | ln=len(p)+2 118 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['foto']%ln, p)) 119 | 120 | @route('/live') 121 | def live(cs,v): # live stream 122 | cs.write(b'%s\r\n\r\n' % hdr['stream']) 123 | cs.setblocking(True) 124 | pic=camera.capture 125 | put=cs.write 126 | hr=hdr['frame'] 127 | while True: 128 | try: 129 | put(b'%s\r\n\r\n' % hr) 130 | put(pic()) 131 | put(b'\r\n') # send and flush the send buffer 132 | except Exception as e: 133 | print(e) 134 | break 135 | 136 | @route('/snap') 137 | def snap(cs,v): 138 | global ip,rot 139 | p=pg['foto']%(f'http://{ip}/foto',rot) 140 | ln=len(p)+2 141 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['foto']%ln, p)) 142 | 143 | @route('/blitz') 144 | def blitz(cs,v): 145 | global ip,rot 146 | p=pg['foto']%(f'http://{ip}/boto',rot) 147 | ln=len(p)+2 148 | cs.write(b'%s\r\n\r\n%s\r\n' % (hdr['foto']%ln, p)) 149 | 150 | @route('/foto') 151 | def foto(cs,v): # still photo 152 | #buf=camera.capture() 153 | #ln=len(buf) 154 | cs.setblocking(True) 155 | cs.write(b'%s\r\n\r\n' % hdr['pic']) 156 | cs.write(camera.capture()) 157 | cs.write(b'\r\n') # send and flush the send buffer 158 | #nc=cs.write(b'%s\r\n\r\n' % (hdr['pix']%ln)+buf) 159 | 160 | @route('/boto') 161 | def boto(cs,v): # still photo blitz on 162 | #buf=camera.capture() 163 | #ln=len(buf) 164 | cs.setblocking(True) 165 | cs.write(b'%s\r\n\r\n' % hdr['pic']) 166 | flash_light.on() 167 | cs.write(camera.capture()) 168 | flash_light.off() 169 | cs.write(b'\r\n') 170 | #nc=cs.write(b'%s\r\n\r\n' % (hdr['pix']%ln)+buf) 171 | 172 | @route('/rot') 173 | def rotate(cs,v): 174 | global rot 175 | rot=v 176 | OK(cs) 177 | 178 | @route('/flash') 179 | def flash(cs,v): 180 | if v==1: flash_light.on() 181 | else: flash_light.off() 182 | OK(cs) 183 | 184 | @route('/fmt') 185 | def fmt(cs,w): 186 | setting(cs,w,(w>=1 and w<=9),camera.pixformat,'pixformat') 187 | 188 | @route('/pix') 189 | def pix(cs,w): 190 | setting(cs,w,(w>0 and w<18),camera.framesize,'framesize') 191 | 192 | @route('/qua') 193 | def qua(cs,w): 194 | setting(cs,w,(w>9 and w<64),camera.quality,'quality') 195 | 196 | @route('/con') 197 | def con(cs,w): 198 | setting(cs,w,(w>-3 and w<3),camera.contrast,'contrast') 199 | 200 | @route('/sat') 201 | def sat(cs,w): 202 | setting(cs,w,(w>-3 and w<3),camera.saturation,'saturation') 203 | 204 | @route('/bri') 205 | def bri(cs,w): 206 | setting(cs,w,(w>-3 and w<3),camera.brightness,'brightness') 207 | 208 | @route('/ael') 209 | def ael(cs,w): 210 | setting(cs,w,(w>-3 and w<3),camera.aelevels,'aelevels') 211 | 212 | @route('/aec') 213 | def aec(cs,w): 214 | setting(cs,w,(w>=0 and w<=1200),camera.aecvalue,'aecvalue') 215 | 216 | @route('/agc') 217 | def agc(cs,w): 218 | setting(cs,w,(w>=0 and w<=30),camera.agcgain,'agcgain') 219 | 220 | @route('/spe') 221 | def spe(cs,w): 222 | setting(cs,w,(w>=0 and w<7),camera.speffect,'speffect') 223 | 224 | @route('/wbl') 225 | def wbl(cs,w): 226 | setting(cs,w,(w>=0 and w<5),camera.whitebalance,'whitebalance') 227 | 228 | 229 | --------------------------------------------------------------------------------