2020-09-13 21:28:38 +08:00
/*
* primary HTML for the OV2640 camera module
*/
2020-10-07 08:08:18 +08:00
const uint8_t index_ov2640_html [ ] = R " =====(<!doctype html>
2020-09-13 21:28:38 +08:00
< html >
< head >
< meta charset = " utf-8 " >
< meta name = " viewport " content = " width=device-width,initial-scale=1 " >
2020-09-15 06:04:45 +08:00
< title > ESP32 OV2640 < / title >
2020-09-13 21:28:38 +08:00
< link rel = " icon " type = " image/png " sizes = " 32x32 " href = " /favicon-32x32.png " >
< link rel = " icon " type = " image/png " sizes = " 16x16 " href = " /favicon-16x16.png " >
< link rel = " stylesheet " type = " text/css " href = " /style.css " >
< style >
@ media ( min - width : 800 px ) and ( orientation : landscape ) {
# content {
display : flex ;
flex - wrap : nowrap ;
align - items : stretch
}
}
< / style >
< / head >
< body >
< section class = " main " >
< div id = " logo " >
< label for = " nav-toggle-cb " id = " nav-toggle " style = " float:left; " > & # 9776 ; & nbsp ; & nbsp ; Settings & nbsp ; & nbsp ; & nbsp ; & nbsp ; < / label >
< button id = " swap-viewer " style = " float:left; " title = " Swap to simple viewer " > Simple < / button >
< button id = " get-still " style = " float:left; " > Get Still < / button >
< button id = " toggle-stream " style = " float:left; " class = " hidden " > Start Stream < / button >
< div id = " wait-settings " style = " float:left; " class = " loader " title = " Waiting for camera settings to load " > < / div >
< / div >
< div id = " content " >
< div class = " hidden " id = " sidebar " >
< input type = " checkbox " id = " nav-toggle-cb " checked = " checked " >
< nav id = " menu " >
2022-03-10 21:44:26 +08:00
< div class = " input-group hidden " id = " lamp-group " title = " Flashlight LED.

Warning:
Built-In lamps can be Very Bright! Avoid looking directly at LED
Can draw a lot of power and may cause visual artifacts, affect WiFi or even brownout the camera on high settings " >
2020-09-13 21:28:38 +08:00
< label for = " lamp " > Light < / label >
< div class = " range-min " > Off < / div >
< input type = " range " id = " lamp " min = " 0 " max = " 100 " value = " 0 " class = " default-action " >
2022-03-10 21:44:26 +08:00
< div class = " range-max " > < span style = " font-size: 125%; " > & # 9888 ; < / span > Full < / div >
2020-09-13 21:28:38 +08:00
< / div >
2022-03-10 21:44:26 +08:00
< div class = " input-group hidden " id = " autolamp-group " title = " When enabled the lamp will only turn on while the camera is active " >
2020-10-26 07:04:21 +08:00
< label for = " autolamp " > Auto Lamp < / label >
< div class = " switch " >
2022-03-09 18:55:03 +08:00
< input id = " autolamp " type = " checkbox " class = " default-action " >
2020-10-26 07:04:21 +08:00
< label class = " slider " for = " autolamp " > < / label >
< / div >
< / div >
2022-03-10 21:44:26 +08:00
< div class = " input-group " id = " framesize-group " title = " Camera resolution
Higher resolutions will result in lower framerates " >
2020-09-13 21:28:38 +08:00
< label for = " framesize " > Resolution < / label >
< select id = " framesize " class = " default-action " >
2021-05-03 16:35:12 +08:00
< option value = " 13 " > UXGA ( 1600 x1200 ) < / option >
< option value = " 12 " > SXGA ( 1280 x1024 ) < / option >
< option value = " 11 " > HD ( 1280 x720 ) < / option >
< option value = " 10 " > XGA ( 1024 x768 ) < / option >
< option value = " 9 " > SVGA ( 800 x600 ) < / option >
< option value = " 8 " > VGA ( 640 x480 ) < / option >
< option value = " 7 " > HVGA ( 480 x320 ) < / option >
< option value = " 6 " > CIF ( 400 x296 ) < / option >
< option value = " 5 " > QVGA ( 320 x240 ) < / option >
< option value = " 3 " > HQVGA ( 240 x176 ) < / option >
< option value = " 1 " > QQVGA ( 160 x120 ) < / option >
< option value = " 0 " > THUMB ( 96 x96 ) < / option >
2020-09-13 21:28:38 +08:00
< / select >
< / div >
2022-03-10 21:44:26 +08:00
< div class = " input-group " id = " quality-group " title = " Camera Image and Stream quality factor
Higher settings will result in lower framerates " >
2020-09-13 21:28:38 +08:00
< label for = " quality " > Quality < / label >
2022-03-10 21:44:26 +08:00
< div class = " range-min " > Low < / div >
2021-03-07 05:28:27 +08:00
< ! - - Note ; the following element is ' flipped ' in CSS so that it slides from High to Low
As a result the ' min ' and ' max ' values are reversed here too - - >
2021-05-11 17:38:59 +08:00
< input type = " range " id = " quality " min = " 6 " max = " 63 " value = " 10 " class = " default-action " >
2022-03-10 21:44:26 +08:00
< div class = " range-max " > High < / div >
2020-09-13 21:28:38 +08:00
< / div >
2022-03-10 21:44:26 +08:00
< div class = " input-group " id = " set-xclk-group " title = " Camera Bus Clock Frequency
Increasing this will raise the camera framerate and capture speed

Raising too far will result in visual artifacts and/or incomplete frames
This setting can vary a lot between boards, budget boards typically need lower values " >
2022-03-08 18:34:45 +08:00
< label for = " set-xclk " > XCLK < / label >
< div class = " text " >
2022-03-10 21:44:26 +08:00
< input id = " xclk " type = " number " min = " 2 " max = " 32 " size = " 3 " step = " 1 " class = " default-action " >
2022-03-08 18:34:45 +08:00
< div class = " range-max " > MHz < / div >
< / div >
< / div >
2020-09-13 21:28:38 +08:00
< div class = " input-group " id = " brightness-group " >
< label for = " brightness " > Brightness < / label >
< div class = " range-min " > - 2 < / div >
< input type = " range " id = " brightness " min = " -2 " max = " 2 " value = " 0 " class = " default-action " >
< div class = " range-max " > 2 < / div >
< / div >
< div class = " input-group " id = " contrast-group " >
< label for = " contrast " > Contrast < / label >
< div class = " range-min " > - 2 < / div >
< input type = " range " id = " contrast " min = " -2 " max = " 2 " value = " 0 " class = " default-action " >
< div class = " range-max " > 2 < / div >
< / div >
< div class = " input-group " id = " saturation-group " >
< label for = " saturation " > Saturation < / label >
< div class = " range-min " > - 2 < / div >
< input type = " range " id = " saturation " min = " -2 " max = " 2 " value = " 0 " class = " default-action " >
< div class = " range-max " > 2 < / div >
< / div >
< div class = " input-group " id = " special_effect-group " >
< label for = " special_effect " > Special Effect < / label >
< select id = " special_effect " class = " default-action " >
< option value = " 0 " selected = " selected " > No Effect < / option >
< option value = " 1 " > Negative < / option >
< option value = " 2 " > Grayscale < / option >
< option value = " 3 " > Red Tint < / option >
< option value = " 4 " > Green Tint < / option >
< option value = " 5 " > Blue Tint < / option >
< option value = " 6 " > Sepia < / option >
< / select >
< / div >
< div class = " input-group " id = " awb-group " >
2022-03-10 21:44:26 +08:00
< label for = " awb " > AWB Enable < / label >
2020-09-13 21:28:38 +08:00
< div class = " switch " >
< input id = " awb " type = " checkbox " class = " default-action " checked = " checked " >
< label class = " slider " for = " awb " > < / label >
< / div >
< / div >
< div class = " input-group " id = " awb_gain-group " >
2022-03-10 21:44:26 +08:00
< label for = " awb_gain " > Manual AWB Gain < / label >
2020-09-13 21:28:38 +08:00
< div class = " switch " >
< input id = " awb_gain " type = " checkbox " class = " default-action " checked = " checked " >
< label class = " slider " for = " awb_gain " > < / label >
< / div >
< / div >
< div class = " input-group " id = " wb_mode-group " >
< label for = " wb_mode " > WB Mode < / label >
< select id = " wb_mode " class = " default-action " >
< option value = " 0 " selected = " selected " > Auto < / option >
< option value = " 1 " > Sunny < / option >
< option value = " 2 " > Cloudy < / option >
< option value = " 3 " > Office < / option >
< option value = " 4 " > Home < / option >
< / select >
< / div >
< div class = " input-group " id = " aec-group " >
2022-03-10 21:44:26 +08:00
< label for = " aec " > AEC Sensor Enable < / label >
2020-09-13 21:28:38 +08:00
< div class = " switch " >
< input id = " aec " type = " checkbox " class = " default-action " checked = " checked " >
< label class = " slider " for = " aec " > < / label >
< / div >
< / div >
< div class = " input-group " id = " aec2-group " >
< label for = " aec2 " > AEC DSP < / label >
< div class = " switch " >
< input id = " aec2 " type = " checkbox " class = " default-action " checked = " checked " >
< label class = " slider " for = " aec2 " > < / label >
< / div >
< / div >
< div class = " input-group " id = " ae_level-group " >
< label for = " ae_level " > AE Level < / label >
< div class = " range-min " > - 2 < / div >
< input type = " range " id = " ae_level " min = " -2 " max = " 2 " value = " 0 " class = " default-action " >
< div class = " range-max " > 2 < / div >
< / div >
< div class = " input-group " id = " aec_value-group " >
< label for = " aec_value " > Exposure < / label >
< div class = " range-min " > 0 < / div >
< input type = " range " id = " aec_value " min = " 0 " max = " 1200 " value = " 204 " class = " default-action " >
< div class = " range-max " > 1200 < / div >
< / div >
< div class = " input-group " id = " agc-group " >
< label for = " agc " > AGC < / label >
< div class = " switch " >
< input id = " agc " type = " checkbox " class = " default-action " checked = " checked " >
< label class = " slider " for = " agc " > < / label >
< / div >
< / div >
< div class = " input-group hidden " id = " agc_gain-group " >
< label for = " agc_gain " > Gain < / label >
< div class = " range-min " > 1 x < / div >
< input type = " range " id = " agc_gain " min = " 0 " max = " 30 " value = " 5 " class = " default-action " >
< div class = " range-max " > 31 x < / div >
< / div >
< div class = " input-group " id = " gainceiling-group " >
< label for = " gainceiling " > Gain Ceiling < / label >
< div class = " range-min " > 2 x < / div >
< input type = " range " id = " gainceiling " min = " 0 " max = " 6 " value = " 0 " class = " default-action " >
< div class = " range-max " > 128 x < / div >
< / div >
< div class = " input-group " id = " bpc-group " >
< label for = " bpc " > BPC < / label >
< div class = " switch " >
< input id = " bpc " type = " checkbox " class = " default-action " >
< label class = " slider " for = " bpc " > < / label >
< / div >
< / div >
< div class = " input-group " id = " wpc-group " >
< label for = " wpc " > WPC < / label >
< div class = " switch " >
< input id = " wpc " type = " checkbox " class = " default-action " checked = " checked " >
< label class = " slider " for = " wpc " > < / label >
< / div >
< / div >
< div class = " input-group " id = " raw_gma-group " >
2022-03-10 21:44:26 +08:00
< label for = " raw_gma " > Raw GMA Enable < / label >
2020-09-13 21:28:38 +08:00
< div class = " switch " >
< input id = " raw_gma " type = " checkbox " class = " default-action " checked = " checked " >
< label class = " slider " for = " raw_gma " > < / label >
< / div >
< / div >
< div class = " input-group " id = " lenc-group " >
< label for = " lenc " > Lens Correction < / label >
< div class = " switch " >
< input id = " lenc " type = " checkbox " class = " default-action " checked = " checked " >
< label class = " slider " for = " lenc " > < / label >
< / div >
< / div >
< div class = " input-group " id = " hmirror-group " >
< label for = " hmirror " > H - Mirror Stream < / label >
< div class = " switch " >
< input id = " hmirror " type = " checkbox " class = " default-action " checked = " checked " >
< label class = " slider " for = " hmirror " > < / label >
< / div >
< / div >
< div class = " input-group " id = " vflip-group " >
< label for = " vflip " > V - Flip Stream < / label >
< div class = " switch " >
< input id = " vflip " type = " checkbox " class = " default-action " checked = " checked " >
< label class = " slider " for = " vflip " > < / label >
< / div >
< / div >
< div class = " input-group " id = " rotate-group " >
< label for = " rotate " > Rotate in Browser < / label >
< select id = " rotate " class = " default-action " >
< option value = " 90 " > 90 & deg ; ( Right ) < / option >
< option value = " 0 " selected = " selected " > 0 & deg ; ( None ) < / option >
< option value = " -90 " > - 90 & deg ; ( Left ) < / option >
< / select >
< / div >
< div class = " input-group " id = " dcw-group " >
< label for = " dcw " > DCW ( Downsize EN ) < / label >
< div class = " switch " >
< input id = " dcw " type = " checkbox " class = " default-action " checked = " checked " >
< label class = " slider " for = " dcw " > < / label >
< / div >
< / div >
< div class = " input-group " id = " colorbar-group " >
2020-09-27 21:21:44 +08:00
< label for = " colorbar " > Test Pattern < / label >
2020-09-13 21:28:38 +08:00
< div class = " switch " >
< input id = " colorbar " type = " checkbox " class = " default-action " >
< label class = " slider " for = " colorbar " > < / label >
< / div >
< / div >
2022-03-10 21:44:26 +08:00
< div class = " input-group " id = " min_frame_time-group " title = " Minimum frame time
Higher settings reduce the frame rate
Use this for a smoother stream and to reduce load on the WiFi and browser " >
2021-12-18 19:39:52 +08:00
< label for = " min_frame_time " > Frame Duration Limit < / label >
2021-12-18 19:29:43 +08:00
< select id = " min_frame_time " class = " default-action " >
2022-03-10 21:44:26 +08:00
< option value = " 3333 " > 3.3 s ( 0.3f ps ) < / option >
< option value = " 2000 " > 2 s ( 0.5f ps ) < / option >
< option value = " 1000 " > 1 s ( 1f ps ) < / option >
2021-12-18 19:39:52 +08:00
< option value = " 500 " > 500 ms ( 2f ps ) < / option >
< option value = " 333 " > 333 ms ( 3f ps ) < / option >
< option value = " 200 " > 200 ms ( 5f ps ) < / option >
< option value = " 100 " > 100 ms ( 10f ps ) < / option >
< option value = " 50 " > 50 ms ( 20f ps ) < / option >
2021-12-17 05:15:01 +08:00
< option value = " 0 " selected = " selected " > Disabled < / option >
< / select >
< / div >
2020-09-27 21:21:44 +08:00
< div class = " input-group " id = " preferences-group " >
2022-03-09 19:03:06 +08:00
< label for = " prefs " style = " line-height: 2em; " > Preferences < / label >
2020-09-27 21:21:44 +08:00
< button id = " reboot " title = " Reboot the camera module " > Reboot < / button >
< button id = " save_prefs " title = " Save Preferences on camera module " > Save < / button >
< button id = " clear_prefs " title = " Erase saved Preferences on camera module " > Erase < / button >
< / div >
2020-09-13 21:28:38 +08:00
< div class = " input-group " id = " cam_name-group " >
2020-10-04 01:49:08 +08:00
< label for = " cam_name " >
< a href = " /dump " title = " System Info " target = " _blank " > Name < / a > < / label >
2020-09-13 21:28:38 +08:00
< div id = " cam_name " class = " default-action " > < / div >
< / div >
< div class = " input-group " id = " code_ver-group " >
< label for = " code_ver " >
< a href = " https://github.com/easytarget/esp32-cam-webserver "
2020-09-15 06:04:45 +08:00
title = " ESP32 Cam Webserver on GitHub " target = " _blank " > Firmware < / a > < / label >
2020-09-13 21:28:38 +08:00
< div id = " code_ver " class = " default-action " > < / div >
< / div >
< div class = " input-group hidden " id = " stream-group " >
2020-10-07 08:08:18 +08:00
< label for = " stream_url " id = " stream_link " > Stream < / label >
2020-09-13 21:28:38 +08:00
< div id = " stream_url " class = " default-action " > Unknown < / div >
< / div >
< / nav >
< / div >
< figure >
< div id = " stream-container " class = " image-container hidden " >
< div class = " close close-rot-none " id = " close-stream " > × < / div >
< img id = " stream " src = " " >
< / div >
< / figure >
< / div >
< / section >
< / body >
< script >
document . addEventListener ( ' DOMContentLoaded ' , function ( event ) {
var baseHost = document . location . origin ;
var streamURL = ' Undefined ' ;
2020-10-04 01:49:08 +08:00
var viewerURL = ' Undefined ' ;
2020-09-13 21:28:38 +08:00
2020-11-21 00:05:00 +08:00
const header = document . getElementById ( ' logo ' )
2020-09-13 21:28:38 +08:00
const settings = document . getElementById ( ' sidebar ' )
const waitSettings = document . getElementById ( ' wait - settings ' )
const lampGroup = document . getElementById ( ' lamp - group ' )
2020-10-26 07:04:21 +08:00
const autolampGroup = document . getElementById ( ' autolamp - group ' )
2020-09-13 21:28:38 +08:00
const streamGroup = document . getElementById ( ' stream - group ' )
const camName = document . getElementById ( ' cam_name ' )
const codeVer = document . getElementById ( ' code_ver ' )
const rotate = document . getElementById ( ' rotate ' )
const view = document . getElementById ( ' stream ' )
const viewContainer = document . getElementById ( ' stream - container ' )
const stillButton = document . getElementById ( ' get - still ' )
const streamButton = document . getElementById ( ' toggle - stream ' )
const closeButton = document . getElementById ( ' close - stream ' )
2020-09-15 06:04:45 +08:00
const streamLink = document . getElementById ( ' stream_link ' )
2020-09-13 21:28:38 +08:00
const framesize = document . getElementById ( ' framesize ' )
2022-03-08 18:34:45 +08:00
const xclk = document . getElementById ( ' xclk ' )
2020-09-13 21:28:38 +08:00
const swapButton = document . getElementById ( ' swap - viewer ' )
2020-09-27 21:21:44 +08:00
const savePrefsButton = document . getElementById ( ' save_prefs ' )
const clearPrefsButton = document . getElementById ( ' clear_prefs ' )
const rebootButton = document . getElementById ( ' reboot ' )
2021-12-18 19:29:43 +08:00
const minFrameTime = document . getElementById ( ' min_frame_time ' )
2020-09-13 21:28:38 +08:00
const hide = el = > {
el . classList . add ( ' hidden ' )
}
const show = el = > {
el . classList . remove ( ' hidden ' )
}
const disable = el = > {
el . classList . add ( ' disabled ' )
el . disabled = true
}
const enable = el = > {
el . classList . remove ( ' disabled ' )
el . disabled = false
}
const updateValue = ( el , value , updateRemote ) = > {
updateRemote = updateRemote = = null ? true : updateRemote
let initialValue
if ( el . type = = = ' checkbox ' ) {
initialValue = el . checked
value = ! ! value
el . checked = value
} else {
initialValue = el . value
el . value = value
}
2020-09-15 06:04:45 +08:00
2020-09-13 21:28:38 +08:00
if ( updateRemote & & initialValue ! = = value ) {
updateConfig ( el ) ;
} else if ( ! updateRemote ) {
if ( el . id = = = " aec " ) {
value ? hide ( exposure ) : show ( exposure )
} else if ( el . id = = = " agc " ) {
if ( value ) {
show ( gainCeiling )
hide ( agcGain )
} else {
hide ( gainCeiling )
show ( agcGain )
}
} else if ( el . id = = = " awb_gain " ) {
value ? show ( wb ) : hide ( wb )
} else if ( el . id = = = " lamp " ) {
2022-03-09 15:40:00 +08:00
if ( value = = - 1 ) {
2020-09-13 21:28:38 +08:00
hide ( lampGroup )
2020-10-26 07:04:21 +08:00
hide ( autolampGroup )
2020-09-13 21:28:38 +08:00
} else {
show ( lampGroup )
2020-10-26 07:04:21 +08:00
show ( autolampGroup )
2020-09-13 21:28:38 +08:00
}
} else if ( el . id = = = " cam_name " ) {
camName . innerHTML = value ;
window . document . title = value ;
console . log ( ' Name set to : ' + value ) ;
} else if ( el . id = = = " code_ver " ) {
codeVer . innerHTML = value ;
console . log ( ' Firmware Build : ' + value ) ;
} else if ( el . id = = = " rotate " ) {
rotate . value = value ;
applyRotation ( ) ;
2021-12-18 19:29:43 +08:00
} else if ( el . id = = = " min_frame_time " ) {
min_frame_time . value = value ;
2020-09-13 21:28:38 +08:00
} else if ( el . id = = = " stream_url " ) {
2020-10-04 01:49:08 +08:00
streamURL = value ;
viewerURL = value + ' view ' ;
2020-09-13 21:28:38 +08:00
stream_url . innerHTML = value ;
2020-10-26 07:04:21 +08:00
stream_link . setAttribute ( " title " , ` Open the standalone stream viewer : : $ { viewerURL } ` ) ;
2020-09-15 06:04:45 +08:00
stream_link . style . textDecoration = " underline " ;
stream_link . style . cursor = " pointer " ;
2020-10-26 07:04:21 +08:00
streamButton . setAttribute ( " title " , ` Start the stream : : $ { streamURL } ` ) ;
2020-09-13 21:28:38 +08:00
show ( streamGroup )
2020-10-04 01:49:08 +08:00
console . log ( ' Stream URL set to : ' + streamURL ) ;
console . log ( ' Stream Viewer URL set to : ' + viewerURL ) ;
2022-03-09 15:40:00 +08:00
}
2020-09-13 21:28:38 +08:00
}
}
2021-09-26 09:00:15 +08:00
var rangeUpdateScheduled = false
var latestRangeConfig
function updateRangeConfig ( el ) {
latestRangeConfig = el
if ( ! rangeUpdateScheduled ) {
rangeUpdateScheduled = true ;
setTimeout ( function ( ) {
rangeUpdateScheduled = false
updateConfig ( latestRangeConfig )
} , 150 ) ;
}
}
2020-09-13 21:28:38 +08:00
function updateConfig ( el ) {
let value
switch ( el . type ) {
case ' checkbox ' :
value = el . checked ? 1 : 0
break
case ' range ' :
2022-03-08 18:34:45 +08:00
case ' number ' :
2020-09-13 21:28:38 +08:00
case ' select - one ' :
value = el . value
break
case ' button ' :
case ' submit ' :
value = ' 1 '
break
default :
return
}
const query = ` $ { baseHost } / control ? var = $ { el . id } & val = $ { value } `
fetch ( query )
. then ( response = > {
console . log ( ` request to $ { query } finished , status : $ { response . status } ` )
} )
}
document
. querySelectorAll ( ' . close ' )
. forEach ( el = > {
el . onclick = ( ) = > {
hide ( el . parentNode )
}
} )
// read initial values
fetch ( ` $ { baseHost } / status ` )
. then ( function ( response ) {
return response . json ( )
} )
. then ( function ( state ) {
document
. querySelectorAll ( ' . default - action ' )
. forEach ( el = > {
updateValue ( el , state [ el . id ] , false )
} )
hide ( waitSettings ) ;
show ( settings ) ;
show ( streamButton ) ;
//startStream();
} )
// Put some helpful text on the 'Still' button
2020-10-26 07:04:21 +08:00
stillButton . setAttribute ( " title " , ` Capture a still image : : $ { baseHost } / capture ` ) ;
2020-09-13 21:28:38 +08:00
const stopStream = ( ) = > {
window . stop ( ) ;
streamButton . innerHTML = ' Start Stream ' ;
2020-10-26 07:04:21 +08:00
streamButton . setAttribute ( " title " , ` Start the stream : : $ { streamURL } ` ) ;
2020-09-13 21:28:38 +08:00
hide ( viewContainer ) ;
}
const startStream = ( ) = > {
view . src = streamURL ;
view . scrollIntoView ( false ) ;
streamButton . innerHTML = ' Stop Stream ' ;
2020-10-26 07:04:21 +08:00
streamButton . setAttribute ( " title " , ` Stop the stream ` ) ;
2020-09-13 21:28:38 +08:00
show ( viewContainer ) ;
}
const applyRotation = ( ) = > {
rot = rotate . value ;
if ( rot = = - 90 ) {
viewContainer . style . transform = ` rotate ( - 90 deg ) translate ( - 100 % ) ` ;
closeButton . classList . remove ( ' close - rot - none ' ) ;
closeButton . classList . remove ( ' close - rot - right ' ) ;
closeButton . classList . add ( ' close - rot - left ' ) ;
} else if ( rot = = 90 ) {
viewContainer . style . transform = ` rotate ( 90 deg ) translate ( 0 , - 100 % ) ` ;
closeButton . classList . remove ( ' close - rot - left ' ) ;
closeButton . classList . remove ( ' close - rot - none ' ) ;
closeButton . classList . add ( ' close - rot - right ' ) ;
} else {
viewContainer . style . transform = ` rotate ( 0 deg ) ` ;
closeButton . classList . remove ( ' close - rot - left ' ) ;
closeButton . classList . remove ( ' close - rot - right ' ) ;
closeButton . classList . add ( ' close - rot - none ' ) ;
}
console . log ( ' Rotation ' + rot + ' applied ' ) ;
}
// Attach actions to controls
2022-03-09 15:40:00 +08:00
2020-09-13 21:28:38 +08:00
streamLink . onclick = ( ) = > {
2020-09-27 21:21:44 +08:00
stopStream ( ) ;
2020-10-04 01:49:08 +08:00
window . open ( viewerURL , " _blank " ) ;
2020-09-13 21:28:38 +08:00
}
stillButton . onclick = ( ) = > {
stopStream ( ) ;
view . src = ` $ { baseHost } / capture ? _cb = $ { Date . now ( ) } ` ;
view . scrollIntoView ( false ) ;
show ( viewContainer ) ;
}
closeButton . onclick = ( ) = > {
stopStream ( ) ;
hide ( viewContainer ) ;
}
streamButton . onclick = ( ) = > {
const streamEnabled = streamButton . innerHTML = = = ' Stop Stream '
if ( streamEnabled ) {
stopStream ( ) ;
} else {
startStream ( ) ;
}
}
// Attach default on change action
document
. querySelectorAll ( ' . default - action ' )
. forEach ( el = > {
el . onchange = ( ) = > updateConfig ( el )
} )
2021-09-26 09:00:15 +08:00
// Update range sliders as they are being moved
document
. querySelectorAll ( ' input [ type = " range " ] ' )
. forEach ( el = > {
el . oninput = ( ) = > updateRangeConfig ( el )
} )
2020-09-13 21:28:38 +08:00
// Custom actions
// Gain
const agc = document . getElementById ( ' agc ' )
const agcGain = document . getElementById ( ' agc_gain - group ' )
const gainCeiling = document . getElementById ( ' gainceiling - group ' )
agc . onchange = ( ) = > {
updateConfig ( agc )
if ( agc . checked ) {
show ( gainCeiling )
hide ( agcGain )
} else {
hide ( gainCeiling )
show ( agcGain )
}
}
2020-09-15 06:04:45 +08:00
2020-09-13 21:28:38 +08:00
// Exposure
const aec = document . getElementById ( ' aec ' )
const exposure = document . getElementById ( ' aec_value - group ' )
aec . onchange = ( ) = > {
updateConfig ( aec )
aec . checked ? hide ( exposure ) : show ( exposure )
}
2020-09-15 06:04:45 +08:00
2020-09-13 21:28:38 +08:00
// AWB
const awb = document . getElementById ( ' awb_gain ' )
const wb = document . getElementById ( ' wb_mode - group ' )
awb . onchange = ( ) = > {
updateConfig ( awb )
awb . checked ? show ( wb ) : hide ( wb )
}
2020-09-15 06:04:45 +08:00
2020-09-13 21:28:38 +08:00
// Detection and framesize
rotate . onchange = ( ) = > {
applyRotation ( ) ;
updateConfig ( rotate ) ;
}
framesize . onchange = ( ) = > {
updateConfig ( framesize )
}
2021-12-18 19:29:43 +08:00
minFrameTime . onchange = ( ) = > {
updateConfig ( minFrameTime )
2022-03-10 21:44:26 +08:00
}
2022-03-09 23:34:18 +08:00
2022-03-08 18:34:45 +08:00
xclk . onchange = ( ) = > {
console . log ( " xclk: " , xclk ) ;
updateConfig ( xclk )
2021-12-17 05:15:01 +08:00
}
2020-09-13 21:28:38 +08:00
swapButton . onclick = ( ) = > {
2020-10-07 08:08:18 +08:00
window . open ( ' / ? view = simple ' , ' _self ' ) ;
2020-09-13 21:28:38 +08:00
}
2022-03-09 15:40:00 +08:00
2020-09-27 21:21:44 +08:00
savePrefsButton . onclick = ( ) = > {
if ( confirm ( " Save the current preferences? " ) ) {
updateConfig ( savePrefsButton ) ;
}
}
clearPrefsButton . onclick = ( ) = > {
if ( confirm ( " Remove the saved preferences? " ) ) {
updateConfig ( clearPrefsButton ) ;
}
}
rebootButton . onclick = ( ) = > {
if ( confirm ( " Reboot the Camera Module? " ) ) {
updateConfig ( rebootButton ) ;
// Some sort of countdown here?
2020-11-21 00:05:00 +08:00
hide ( settings ) ;
hide ( viewContainer ) ;
header . innerHTML = ' < h1 > Rebooting ! < / h1 > < hr > Page will reload after 30 seconds . ' ;
setTimeout ( function ( ) {
location . replace ( document . URL ) ;
} , 30000 ) ;
2020-09-27 21:21:44 +08:00
}
}
2020-09-13 21:28:38 +08:00
} )
< / script >
2020-10-07 08:08:18 +08:00
< / html > ) = = = = = " ;
2020-09-13 21:28:38 +08:00
2020-10-07 08:08:18 +08:00
size_t index_ov2640_html_len = sizeof ( index_ov2640_html ) - 1 ;