diff --git a/app/package.json b/app/package.json
index 5f73e1d..68a8200 100644
--- a/app/package.json
+++ b/app/package.json
@@ -49,4 +49,4 @@
"android"
]
}
-}
+}
\ No newline at end of file
diff --git a/app/www/index.html b/app/www/index.html
index 3cc8e45..08ba44a 100644
--- a/app/www/index.html
+++ b/app/www/index.html
@@ -88,6 +88,7 @@
+
v1.0.7 build cfb0a7be
+
diff --git a/app/www/static/css/index.css b/app/www/static/css/index.css
index 476a9bb..2e86273 100644
--- a/app/www/static/css/index.css
+++ b/app/www/static/css/index.css
@@ -237,6 +237,11 @@ button.focus{
.cameraIcon{
background: url(data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTguMS4xLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEwMCAxMDA7IiB4bWw6c3BhY2U9InByZXNlcnZlIiB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4Ij4KPGc+Cgk8Zz4KCQk8cGF0aCBkPSJNNTAsNDBjLTguMjg1LDAtMTUsNi43MTgtMTUsMTVjMCw4LjI4NSw2LjcxNSwxNSwxNSwxNWM4LjI4MywwLDE1LTYuNzE1LDE1LTE1ICAgIEM2NSw0Ni43MTgsNTguMjgzLDQwLDUwLDQweiBNOTAsMjVINzhjLTEuNjUsMC0zLjQyOC0xLjI4LTMuOTQ5LTIuODQ2bC0zLjEwMi05LjMwOUM3MC40MjYsMTEuMjgsNjguNjUsMTAsNjcsMTBIMzMgICAgYy0xLjY1LDAtMy40MjgsMS4yOC0zLjk0OSwyLjg0NmwtMy4xMDIsOS4zMDlDMjUuNDI2LDIzLjcyLDIzLjY1LDI1LDIyLDI1SDEwQzQuNSwyNSwwLDI5LjUsMCwzNXY0NWMwLDUuNSw0LjUsMTAsMTAsMTBoODAgICAgYzUuNSwwLDEwLTQuNSwxMC0xMFYzNUMxMDAsMjkuNSw5NS41LDI1LDkwLDI1eiBNNTAsODBjLTEzLjgwNywwLTI1LTExLjE5My0yNS0yNWMwLTEzLjgwNiwxMS4xOTMtMjUsMjUtMjUgICAgYzEzLjgwNSwwLDI1LDExLjE5NCwyNSwyNUM3NSw2OC44MDcsNjMuODA1LDgwLDUwLDgweiBNODYuNSw0MS45OTNjLTEuOTMyLDAtMy41LTEuNTY2LTMuNS0zLjVjMC0xLjkzMiwxLjU2OC0zLjUsMy41LTMuNSAgICBjMS45MzQsMCwzLjUsMS41NjgsMy41LDMuNUM5MCw0MC40MjcsODguNDMzLDQxLjk5Myw4Ni41LDQxLjk5M3oiIGZpbGw9IiNGRkZGRkYiLz4KCTwvZz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8L3N2Zz4K) no-repeat;
}
+#advancedIcon > div {
+ filter: invert(1);
+ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAAD3UlEQVRoge3Zz28VVRQH8E9LWzRRo9S6wJqYKBASXWgtAmowGv8CDabBjSGGhf8G/sBl8ddSA7oxblAkoDExxhj8sRETjRgMaJUqrkRqacNzce84j/Y93rtzZ6pEvsnkvndnzvecM/fcH+cMV/D/wQj24GfM4LnYd9nhebSWXM/+qxZVxIxg/BZsjb9nmlI21BSxMozOtvUNN6VsVVPEuBWTuB4P4E68jvca1NkIxjGHC/Gai32NoM7QGsS92IZNuE0Y8YF4fxUO4nt8ho9wVJg7/wmMCyvUT5avUr2uH4Vl+eYVt7oNY3gR55WGHY99U7gLa4QJPozR2DeFl4SRKeTOYxo3rqgH2I4z0YgF7MPmCjxbsD9ytPAbHqvJxktiGC8r3+RB3F4D73ocauPdq8Gt4ao2ZX/iyT7ljuLTPp/dGblbeBerE23siSFh/W/htBDr/aJ4y/1iArNKZ2odmVeUTqxPlE11RNRROLM3UbYrHleGU8pIFKjiCGFkzkXZRyvIX4Qx/B7J+p0TS1HVEXhKuZqNVuRAGVI556McR+BwlJ+uSnCLsFEtyFticx3ZgEXMY20VgiIx2pdhBPmOwBsqJmaDyrNTlR27HXU4UiRmpwTbkgWPZxpAPY4M4ETk2dTpgW7ebYvt4UwD6kILR+LvBzs90M2Rydh+UrNBOfg4tkkjsi6232QoHsHutv8vyMvZC1vWXfKpJSg2wZxNaLflidSeDL6xyHEmRWg+CuUU1E5Z7sgvGXyrI8d8p5tJS1kiOnEPdOhLRccVsJsjRS3q2orKxoTdeCleq8gH18X2jxShrwXPq5x2b8KxKH9SKDCcFuZHzmSfiJxfpQi9HYWmEpW1O3Es/q8LT0Tetzrd7BZaX8b2/gRFY/gAd+BbPIJfE+R7obDlixShzcojSj8TtMmREG34IfJP9nj2IgwKsV1U03vhc805Afcp51zHKOoWWheEehM83YeiRSEcH1ZvOBUobNgv2JaEcWHzWZBecKgTG4UXNadiYkVZjDtUk1FV8L7MVJdw1ipKoztrMCoVu6LuWdyQS9ZeDprIJUvApBBOLTXWg4sQm7Uy82WDsGhkh9RSDOEdpTNNjsyk0okDGihmX6105pxQPKsbu5ThdCDqbARDwkeaIr84IoRBLjYqV6cinJr84vwPtiuHf1GoO22Vlm8MCDv2m5GjCNsV+dDTjjVCpfwv5Zs8IZRZd+BuYfkeideoMLd24FXl2aklhNO0GpbYHKzFMzqntr2uk0JuX3nHLlBH6llgEPfgIeHNbxC+1l4T758VqpffCUfxD4XzWfLZ6QouB/wNDUkks50hozcAAAAASUVORK5CYII=) no-repeat;
+ background-size: 33px 33px;
+}
button i {
display: block;
@@ -255,8 +260,8 @@ footer{
}
footer .icon {
- /*width: 33.33%;*/
- width: 50%;
+ width: 33.33%;
+ /*width: 50%;*/
height: 50px;
float: left;
box-sizing: border-box;
@@ -264,8 +269,8 @@ footer .icon {
}
body.mobile footer .icon{
- /*width: 25%;*/
- width: 33.33%;
+ width: 25%;
+ /*width: 33.33%;*/
}
footer .icon:last-child{
@@ -440,4 +445,25 @@ body.mobile footer{
line-height: 100vh;
text-shadow: 1px 1px 0px #999;
font-size: 24px;
+}
+
+#version{
+ bottom: 70px;
+ position: absolute;
+ color: #666;
+}
+
+#stats{
+ margin: 10px 0;
+ font-size: 18px;
+}
+
+#stats label {
+ color: #666;
+ width: 100px;
+ display: inline-block;
+}
+
+#stats span{
+ color: #fff;
}
\ No newline at end of file
diff --git a/app/www/static/js/intval.core.js b/app/www/static/js/intval.core.js
index 8211733..7f7b942 100644
--- a/app/www/static/js/intval.core.js
+++ b/app/www/static/js/intval.core.js
@@ -13,7 +13,8 @@ const STATE = {
scale : 'ms',
delayScale : 'ms',
counter : 0,
- sequence : false
+ sequence : false,
+ advanced : 0
};
//functions
@@ -27,6 +28,7 @@ window.sequence = null;
window.reset = null;
window.restart = null;
window.update = null;
+window.advanced = null;
//ms
var shutter = function (exposure) {
@@ -183,6 +185,8 @@ var setState = function (res) {
document.getElementById('delayScale').value = delayScale;
setDelayScale();
+ calcStats();
+
if (res.sequence == true) {
if (mobile.ble) mobile.ble.active = true;
if (pwa.wble) pwa.wble.active = true;
@@ -195,18 +199,28 @@ var setState = function (res) {
};
var seqState = function (state) {
- const elem = document.getElementById('seq')
+ const elem = document.getElementById('seq');
+ const advancedElem = document.getElementById('run');
+
if (state) {
if (!elem.classList.contains('focus')) {
elem.classList.add('focus');
}
+ if (!advancedElem.classList.contains('focus')) {
+ advancedElem.classList.add('focus');
+ }
elem.innerHTML = 'STOP SEQUENCE';
+ advancedElem.innerHTML = 'STOP';
STATE.sequence = true;
} else {
if (elem.classList.contains('focus')) {
elem.classList.remove('focus');
}
+ if (advancedElem.classList.contains('focus')) {
+ advancedElem.classList.remove('focus');
+ }
elem.innerHTML = 'START SEQUENCE';
+ advancedElem.innerHTML = 'RUN';
STATE.sequence = false;
}
};
@@ -232,11 +246,87 @@ var cameraPage = function () {
document.getElementById('camera').classList.add('selected');
document.getElementById('cameraIcon').classList.add('selected');
};
+var advancedPage = function () {
+ unsetPages();
+ document.getElementById('advanced').classList.add('selected');
+ document.getElementById('advancedIcon').classList.add('selected');
+};
var isNumeric = function (n) {
return !isNaN(parseFloat(n)) && isFinite(n);
};
+var calcStats = function () {
+ const extraFwd = BOLEX.expected;
+ const extraBwd = BOLEX.expected + 150;
+ const total = parseInt(document.getElementById('len').value);
+ const multiple = parseInt(document.getElementById('multiple').value);
+ const filmTime = (total * multiple) / 24;
+ const delays = total - 1;
+ const frameEnd = STATE.counter + (STATE.dir ? total * multiple : -total * multiple);
+
+ let exp;
+ let realTime;
+ let realTimePartial;
+ let realTimeDisplay;
+ let filmTimeDisplay;
+
+ if (STATE.exposure > BOLEX.expected) {
+ exp = STATE.exposure + (STATE.dir ? extraFwd : extraBwd);
+ } else {
+ exp = BOLEX.expected;
+ }
+ realTime = (exp * total * multiple) + (delays * STATE.delay);
+
+ STATE.advanced = realTime;
+
+ if (realTime < 60 * 1000) { //1min
+ realTimeDisplay = Math.floor(realTime * 100) / 100000;
+ realTimeDisplay += ' sec';
+ } else if (realTime >= 60 * 1000 && realTime < 60 * 60 * 1000) { //1hr
+ realTimePartial = Math.floor(realTime * 100) / (60 * 100000);
+ realTimeDisplay = Math.floor(realTimePartial);
+ realTimeDisplay += ' min';
+ if (realTimePartial > Math.floor(realTimePartial)) {
+ realTimeDisplay += ' ' + Math.round((realTimePartial - Math.floor(realTimePartial) ) * 60);
+ realTimeDisplay += ' sec'
+ }
+ } else if (realTime >= 60 * 60 * 1000 && realTime < 24 * 60 * 60 * 1000) { //1day
+ realTimePartial = Math.floor(realTime * 100) / (60 * 60 * 100000);
+ realTimeDisplay = Math.floor(realTimePartial);
+ realTimeDisplay += ' hr';
+ if (realTimePartial > Math.floor(realTimePartial)) {
+ realTimeDisplay += ' ' + Math.round((realTimePartial - Math.floor(realTimePartial) ) * 60);
+ realTimeDisplay += ' min'
+ }
+ } else if (realTime >= 24 * 60 * 60 * 1000 && realTime < 24 * 60 * 60 * 1000) { //1day
+ realTimePartial = Math.floor(realTime * 100) / (60 * 60 * 100000);
+ realTimeDisplay = Math.floor(realTimePartial);
+ realTimeDisplay += ' day';
+ if (realTimePartial > Math.floor(realTimePartial)) {
+ realTimeDisplay += ' ' + Math.round((realTimePartial - Math.floor(realTimePartial) ) * 24);
+ realTimeDisplay += ' hr'
+ }
+ }
+
+ if (filmTime < 60 * 1000) { //1min
+ filmTimeDisplay = Math.floor(filmTime * 100) / 100;
+ filmTimeDisplay += ' sec';
+ } else if (filmTime >= 60 * 1000) {
+ filmTimePartial = Math.floor(filmTime * 100) / (60 * 100000);
+ filmTimeDisplay = Math.floor(filmTimePartial);
+ filmTimeDisplay += ' min';
+ if (filmTimePartial > Math.floor(filmTimePartial)) {
+ filmTimeDisplay += ' ' + Math.round((filmTimePartial - Math.floor(filmTimePartial) ) * 60);
+ filmTimeDisplay += ' sec'
+ }
+ }
+
+ document.getElementById('realTime').innerHTML = realTimeDisplay;
+ document.getElementById('filmTime').innerHTML = filmTimeDisplay;
+ document.getElementById('frameEnd').innerHTML = frameEnd;
+};
+
var UI = {};
UI.overlay = {
@@ -319,4 +409,6 @@ var init = function () {
document.querySelector('.fstop').oninput = function () {
BOLEX.fstop = parseFloat(this.value);
};
+ document.getElementById('len').oninput = calcStats;
+ document.getElementById('multiple').oninput = calcStats;
};
\ No newline at end of file
diff --git a/app/www/static/js/intval.mobile.js b/app/www/static/js/intval.mobile.js
index df6d333..53af62a 100644
--- a/app/www/static/js/intval.mobile.js
+++ b/app/www/static/js/intval.mobile.js
@@ -151,6 +151,7 @@ mobile.init = function () {
window.getWifi = mobile.getWifi;
window.setWifi = mobile.setWifi;
window.editWifi = mobile.editWifi;
+ window.advanced = mobile.advanced;
//show ble-specific fields in settings
for (let i of bleInputs) {
@@ -173,6 +174,7 @@ mobile.getState = function () {
mobile.stateSuccess,
mobile.ble.onError);
};
+
mobile.stateSuccess = function (data) {
let str = bytesToString(data);
let res = JSON.parse(str);
@@ -205,13 +207,13 @@ mobile.frameSuccess = function () {
console.log('Frame finished, getting state.');
mobile.ble.active = false;
document.getElementById('frame').classList.remove('focus');
- mobile.getState();
+ getState();
} else {
setTimeout(() => {
console.log('Frame finished, getting state.');
mobile.ble.active = false;
document.getElementById('frame').classList.remove('focus');
- mobile.getState();
+ getState();
}, STATE.exposure + 500)
}
}
@@ -230,7 +232,7 @@ mobile.setDir = function () {
};
mobile.dirSuccess = function () {
console.log('Set direction');
- mobile.getState();
+ getState();
setTimeout(() => {
setDirLabel(STATE.dir);
}, 50);
@@ -255,7 +257,7 @@ mobile.setExposure = function () {
};
mobile.exposureSuccess = function () {
console.log('Set exposure');
- mobile.getState();
+ getState();
};
mobile.setDelay = function () {
@@ -275,7 +277,7 @@ mobile.setDelay = function () {
mobile.delaySuccess = function () {
console.log('Set delay');
- mobile.getState();
+ getState();
};
mobile.setCounter = function () {
@@ -307,7 +309,7 @@ mobile.setCounter = function () {
mobile.counterSuccess = function () {
console.log('Set counter');
- mobile.getState();
+ getState();
};
mobile.sequence = function () {
@@ -334,18 +336,75 @@ mobile.sequence = function () {
mobile.sequenceSuccess = function () {
console.log('Sequence state changed');
- mobile.getState();
+ getState();
setTimeout(() => {
if (STATE.sequence) {
- mobile.ble.active = true;
seqState(true);
} else {
- mobile.ble.active = false;
seqState(false);
}
- }, 20);
+ }, 42);
};
+mobile.advanced = function () {
+ const len = parseInt(document.getElementById('len').value);
+ const multiple = parseInt(document.getElementById('multiple').value);
+ const opts = {
+ type : 'sequence',
+ len,
+ multiple
+ };
+
+ if (!opts.len) {
+ return mobile.alert('You must set a total frame count.');
+ }
+
+ if (!opts.multiple) {
+ return mobile.alert('You must set a frame multiple value.');
+ }
+ const elem = document.getElementById('run');
+
+ if (!mobile.ble.connected) {
+ return mobile.alert('Not connected to an INTVAL3 device.');
+ }
+ ble.write(mobile.ble.device.id,
+ mobile.ble.SERVICE_ID,
+ mobile.ble.CHAR_ID,
+ stringToBytes(JSON.stringify(opts)), //check length?
+ mobile.advanceSuccess,
+ mobile.ble.onError);
+
+ if (!elem.classList.contains('focus')) {
+ elem.classList.add('focus');
+ }
+
+ mobile.ble.active = true;
+};
+
+mobile.advancedSuccess = function () {
+ console.log('Sequence state changed');
+ getState();
+ setTimeout(() => {
+ if (STATE.sequence) {
+ seqState(true);
+ } else {
+ seqState(false);
+ }
+ document.getElementById('seq').blur();
+ document.getElementById('run').blur();
+ }, 42);
+ setTimeout(() => {
+ console.log('Sequence complete');
+ getState();
+ setTimeout(() => {
+ if (STATE.sequence) {
+ seqState(true);
+ } else {
+ seqState(false);
+ }
+ }, 42);
+ }, STATE.advanced + 1000);
+};
//retreive object with list of available Wifi APs,
//and state of current connection, if available
@@ -471,6 +530,23 @@ mobile.setWifiSuccess = function () {
console.log('Set new wifi credentials');
setTimeout(mobile.getWifi, 100);
};
+
+mobile.getInfo = function () {
+ const opts = {
+ type : 'info'
+ };
+
+ ble.write(mobile.ble.device.id,
+ mobile.ble.SERVICE_ID,
+ mobile.ble.CHAR_ID,
+ stringToBytes(JSON.stringify(opts)), //check length?
+ mobile.dirSuccess,
+ mobile.ble.onError);
+};
+mobile.infoSuccess = function () {
+ console.dir()
+};
+
mobile.exif = {}
mobile.getCamera = function () {
@@ -671,7 +747,7 @@ mobile.reset = function () {
mobile.resetSuccess = function () {
console.log('Reset to default settings');
setTimeout(() => {
- mobile.getState();
+ getState();
}, 100)
};
diff --git a/app/www/static/js/intval.pwa.js b/app/www/static/js/intval.pwa.js
index f6cbbb0..a0f372a 100644
--- a/app/www/static/js/intval.pwa.js
+++ b/app/www/static/js/intval.pwa.js
@@ -263,6 +263,7 @@ pwa.init = function () {
window.getWifi = pwa.getWifi;
window.setWifi = pwa.setWifi;
window.editWifi = pwa.editWifi;
+ window.advanced = pwa.advanced;
//show ble-specific fields in settings
for (let i of bleInputs) {
@@ -481,6 +482,67 @@ pwa.sequenceSuccess = function () {
};
+pwa.advanced = async function () {
+ const len = parseInt(document.getElementById('len').value);
+ const multiple = parseInt(document.getElementById('multiple').value);
+ const opts = {
+ type : 'sequence',
+ len,
+ multiple
+ };
+
+ if (!opts.len) {
+ return pwa.alert('You must set a total frame count.');
+ }
+
+ if (!opts.multiple) {
+ return pwa.alert('You must set a frame multiple value.');
+ }
+ const elem = document.getElementById('run');
+ if (!pwa.wble.connected) {
+ return pwa.alert('Not connected to an INTVAL3 device.');
+ }
+ try {
+ await pwa.wble.write(pwa.wble.CHAR_ID, opts);
+ } catch (err) {
+ console.error(err);
+ pwa.wble.onError(err.message);
+ return false;
+ }
+
+ pwa.advancedSuccess();
+
+ if (!elem.classList.contains('focus')) {
+ elem.classList.add('focus');
+ }
+
+ pwa.wble.active = true;
+};
+
+pwa.advancedSuccess = function () {
+ console.log('Sequence state changed');
+ pwa.getState();
+ setTimeout(() => {
+ if (STATE.sequence) {
+ seqState(true);
+ } else {
+ seqState(false);
+ }
+ document.getElementById('seq').blur();
+ }, 42);
+ setTimeout(() => {
+ console.log('Sequence complete');
+ getState();
+ setTimeout(() => {
+ if (STATE.sequence) {
+ seqState(true);
+ } else {
+ seqState(false);
+ }
+ }, 42);
+ }, STATE.advanced + 1000);
+};
+
//retreive object with list of available Wifi APs,
//and state of current connection, if available
pwa.getWifi = async function () {
diff --git a/app/www/static/js/intval.web.js b/app/www/static/js/intval.web.js
index 1f294ce..06f40fc 100644
--- a/app/www/static/js/intval.web.js
+++ b/app/www/static/js/intval.web.js
@@ -160,6 +160,56 @@ web.sequenceSuccess = function (res) {
mobile.getState();
}
};
+web.advanced = function () {
+ const len = parseInt(document.getElementById('len').value);
+ const multiple = parseInt(document.getElementById('multiple').value);
+ const params = {
+ len,
+ multiple
+ }
+ const opts = {
+ method : 'POST',
+ headers : web._header,
+ body : JSON.stringify(params)
+ }
+ if (!params.len) {
+ return alert('You must set a total frame count.');
+ }
+
+ if (!params.multiple) {
+ return alert('You must set a frame multiple value.');
+ }
+ fetch('/sequence', opts)
+ .then(web.useJson)
+ .then(web.advancedSuccess)
+ .catch(err => {
+ console.error('Error getting /sequence');
+ console.error(err);
+ })
+};
+web.advancedSuccess = function (res) {
+ if (res.started && res.started != false) {
+ STATE.sequence = true;
+ document.getElementById('seq').focus();
+ seqState(true);
+ } else if (res.stopped) {
+ STATE.sequence = false;
+ document.getElementById('seq').blur();
+ seqState(false);
+ getState();
+ }
+ setTimeout(() => {
+ console.log('Sequence complete');
+ getState();
+ setTimeout(() => {
+ if (STATE.sequence) {
+ seqState(true);
+ } else {
+ seqState(false);
+ }
+ }, 42);
+ }, STATE.advanced + 1000);
+};
web.reset = function () {
const opts = {
method : 'POST',
@@ -228,5 +278,6 @@ web.init = function () {
window.reset = web.reset;
window.restart = web.restart;
window.update = web.update;
+ window.advanced = web.advanced;
console.log('started web')
};
\ No newline at end of file