alpha
This commit is contained in:
		
							parent
							
								
									8d25fbdfb4
								
							
						
					
					
						commit
						66141472e1
					
				
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					.idea/
 | 
				
			||||||
 | 
					./node_modules/
 | 
				
			||||||
 | 
					./package-lock.json
 | 
				
			||||||
							
								
								
									
										71
									
								
								public/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								public/index.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html lang="en">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					<meta charset="UTF-8">
 | 
				
			||||||
 | 
					    <title>esp-iot</title>
 | 
				
			||||||
 | 
					    <!-- PWA support -->
 | 
				
			||||||
 | 
					    <link rel="manifest" href="/manifest.json"/>
 | 
				
			||||||
 | 
					    <meta name="theme-color" content="#2F3BA2"/>
 | 
				
			||||||
 | 
					    <meta name="description" content="short your url"/>
 | 
				
			||||||
 | 
					    <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0'/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <link rel="stylesheet" type="text/css" href="/sym/dark.css"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <script>
 | 
				
			||||||
 | 
					        const wsurl = 'ws://192.168.1.101:8081'
 | 
				
			||||||
 | 
					        const socket = new WebSocket(wsurl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        socket.onopen = () => {
 | 
				
			||||||
 | 
					            socket.send('new session')
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        socket.onerror = (error) => {
 | 
				
			||||||
 | 
					            console.log(`WebSocket error: ${error}`)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        socket.onclose = error => show_error('session timed out (refresh)')
 | 
				
			||||||
 | 
					        socket.onmessage = (e) => {
 | 
				
			||||||
 | 
					            console.log(e.data)
 | 
				
			||||||
 | 
					            let msg = e.data.split(";", 2)
 | 
				
			||||||
 | 
					            if (msg[0] === 'error') show_error(msg[1])
 | 
				
			||||||
 | 
					            else if (msg[0] === 'led1') {
 | 
				
			||||||
 | 
					                document.getElementById('led1_title').innerText = `LED 1 (currently ${msg[1]}):`
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        function copy_url() {
 | 
				
			||||||
 | 
					            document.getElementById('surl-input').select()
 | 
				
			||||||
 | 
					            document.execCommand("copy")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        function lurl_submit() {
 | 
				
			||||||
 | 
					            socket.send('long_url;'+document.getElementById('longurl-input').value)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        function show_error(msg) {
 | 
				
			||||||
 | 
					            let error_style = document.getElementById('error-box').style
 | 
				
			||||||
 | 
					            document.getElementById('error-message').innerText = msg
 | 
				
			||||||
 | 
					            error_style.display = "block"
 | 
				
			||||||
 | 
					            error_style.animation = "slide-from-left alternate 0.2s"
 | 
				
			||||||
 | 
					            setTimeout(to => {error_style.animation = ""}, 200)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					    <div class="title">ESP-IoT</div>
 | 
				
			||||||
 | 
					    <div class="title2" id="led1_title">LED 1:</div>
 | 
				
			||||||
 | 
					    <div class="btn-green"
 | 
				
			||||||
 | 
					         style="width: 10rem; position:relative; margin-top: 1rem; margin-left: calc(50% - 5rem);"
 | 
				
			||||||
 | 
					         onclick="socket.send('led1;on')">
 | 
				
			||||||
 | 
					        <div class="btn-text">on</div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div class="btn-red"
 | 
				
			||||||
 | 
					         style="width: 10rem; position:relative; margin-top: 1rem; margin-left: calc(50% - 5rem);"
 | 
				
			||||||
 | 
					         onclick="socket.send('led1;off')">
 | 
				
			||||||
 | 
					        <div class="btn-text">off</div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div id="error-box" class="error">
 | 
				
			||||||
 | 
					        <div onclick="this.parentNode.style.display = 'none'" style="position: absolute; top:5px; right: 5px;" class="sym_btn-invisible">
 | 
				
			||||||
 | 
					            <img class="icon" src="./sym/ic_close_white_24px.svg">
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div id="error-message" class="btn-text">
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										9
									
								
								public/manifest.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								public/manifest.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "ESP IoT",
 | 
				
			||||||
 | 
					  "short_name": "ESP-IoT",
 | 
				
			||||||
 | 
					  "start_url": "/",
 | 
				
			||||||
 | 
					  "display": "standalone",
 | 
				
			||||||
 | 
					  "background_color": "#14181b",
 | 
				
			||||||
 | 
					  "theme_color": "#00BCD4",
 | 
				
			||||||
 | 
					  "orientation": "portrait-primary"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										250
									
								
								public/sym/dark.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								public/sym/dark.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,250 @@
 | 
				
			|||||||
 | 
					html{
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    height: 100%;
 | 
				
			||||||
 | 
					    margin: 0px;
 | 
				
			||||||
 | 
					    background-color: #14181b;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					body{
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    padding-top: 20px;
 | 
				
			||||||
 | 
					    padding-bottom: 130px;
 | 
				
			||||||
 | 
					    min-height: calc(100% - 150px);
 | 
				
			||||||
 | 
					    max-width: 70rem;
 | 
				
			||||||
 | 
					    min-width: 25rem;
 | 
				
			||||||
 | 
					    margin: auto;
 | 
				
			||||||
 | 
					    background-color: #1f262b;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					table{
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    margin: auto;
 | 
				
			||||||
 | 
					    width: calc(100% - 50px);
 | 
				
			||||||
 | 
					    max-width: 600px;
 | 
				
			||||||
 | 
					    background-color: #1f262b;
 | 
				
			||||||
 | 
					    box-shadow: 3px 3px 10px #333;
 | 
				
			||||||
 | 
					    border: 2px solid #fff;
 | 
				
			||||||
 | 
					    border-collapse: separate;
 | 
				
			||||||
 | 
					    border-spacing: 2px;
 | 
				
			||||||
 | 
					    border-radius: 10px;
 | 
				
			||||||
 | 
					    color: #fff;
 | 
				
			||||||
 | 
					    font-size: 15pt;
 | 
				
			||||||
 | 
					    font-family:"Roboto", regular, sans-serif;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					tr{
 | 
				
			||||||
 | 
					    margin: auto;
 | 
				
			||||||
 | 
					    border: 1px solid #fff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					th{
 | 
				
			||||||
 | 
					    margin: auto;
 | 
				
			||||||
 | 
					    border: 0px solid #aaa;
 | 
				
			||||||
 | 
					    background-color: #546E7A;
 | 
				
			||||||
 | 
					    padding: 20px;
 | 
				
			||||||
 | 
					    border-radius: 8px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					td{
 | 
				
			||||||
 | 
					    margin: auto;
 | 
				
			||||||
 | 
					    border: 0px solid #aaa;
 | 
				
			||||||
 | 
					    background-color: #37474F ;
 | 
				
			||||||
 | 
					    padding: 10px;
 | 
				
			||||||
 | 
					    border-radius: 8px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					td.left,th.left{
 | 
				
			||||||
 | 
					    border-radius: 8px 0px 0px 8px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					td.right,th.right{
 | 
				
			||||||
 | 
					    border-radius: 0px 8px 8px 0px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					td.mid,th.mid{
 | 
				
			||||||
 | 
					    border-radius: 0px 0px 0px 0px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					div.input-box {
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    left: calc(50% - 14rem);
 | 
				
			||||||
 | 
					    top: calc(50% - 7rem);
 | 
				
			||||||
 | 
					    width: 28rem;
 | 
				
			||||||
 | 
					    height: 14rem;
 | 
				
			||||||
 | 
					    background-color: #14181b00;
 | 
				
			||||||
 | 
					    border-radius: 8px;
 | 
				
			||||||
 | 
					    border: 0px solid #fff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					div.input-field {
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    margin-left: 5%;
 | 
				
			||||||
 | 
					    margin-top: 20px;
 | 
				
			||||||
 | 
					    width: 90%;
 | 
				
			||||||
 | 
					    height: 2.5rem;
 | 
				
			||||||
 | 
					    background-color: #14181b;
 | 
				
			||||||
 | 
					    border-radius: 1.25rem;
 | 
				
			||||||
 | 
					    border: 1px solid #fff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.input {
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    left: 1rem;
 | 
				
			||||||
 | 
					    top: calc(50% - 1rem);
 | 
				
			||||||
 | 
					    width: calc(100% - 2rem);
 | 
				
			||||||
 | 
					    height: 2rem;
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					    color:#fff;
 | 
				
			||||||
 | 
					    font-size: 15pt;
 | 
				
			||||||
 | 
					    font-family:Arial, "lucida console", sans-serif;
 | 
				
			||||||
 | 
					    border: 0px solid #fff;
 | 
				
			||||||
 | 
					    background-color: transparent;
 | 
				
			||||||
 | 
					    outline: 0 none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					input[id="longurl-input"]::-webkit-input-placeholder {
 | 
				
			||||||
 | 
					    color: #ffffff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.btn-blue{
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					    height: 2.5rem;
 | 
				
			||||||
 | 
					    background-color: #00BCD4;
 | 
				
			||||||
 | 
					    box-shadow: 3px 3px 10px #333;
 | 
				
			||||||
 | 
					    border-radius: 1.25rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.btn-green{
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					    height: 2.5rem;
 | 
				
			||||||
 | 
					    background-color: #009688;
 | 
				
			||||||
 | 
					    box-shadow: 3px 3px 10px #333;
 | 
				
			||||||
 | 
					    border-radius: 1.25rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.btn-red{
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					    height: 2.5rem;
 | 
				
			||||||
 | 
					    background-color: #E53935;
 | 
				
			||||||
 | 
					    box-shadow: 3px 3px 10px #333;
 | 
				
			||||||
 | 
					    border-radius: 1.25rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.btn-text {
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    top: 50%;
 | 
				
			||||||
 | 
					    left: 50%;
 | 
				
			||||||
 | 
					    transform: translate(-50%, -50%);
 | 
				
			||||||
 | 
					    font-size: 1.4rem;
 | 
				
			||||||
 | 
					    color:#fff;
 | 
				
			||||||
 | 
					    font-family:Arial, "lucida console", sans-serif;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.sym_btn-red{
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					    height: 2.5rem;
 | 
				
			||||||
 | 
					    width: 2.5rem;
 | 
				
			||||||
 | 
					    background-color: #E53935;
 | 
				
			||||||
 | 
					    border-radius: 1.25rem;
 | 
				
			||||||
 | 
					    box-shadow: 3px 3px 10px #333;
 | 
				
			||||||
 | 
					    float: left;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.sym_btn-blue{
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					    height: 2.5rem;
 | 
				
			||||||
 | 
					    width: 2.5rem;
 | 
				
			||||||
 | 
					    background-color: #1E88E5;
 | 
				
			||||||
 | 
					    border-radius: 1.25rem;
 | 
				
			||||||
 | 
					    box-shadow: 3px 3px 10px #333;
 | 
				
			||||||
 | 
					    float: left;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.sym_btn-invisible{
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					    height: 2.5rem;
 | 
				
			||||||
 | 
					    width: 2.5rem;
 | 
				
			||||||
 | 
					    border-radius: 1.25rem;
 | 
				
			||||||
 | 
					    float: left;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					img.icon {
 | 
				
			||||||
 | 
					    margin-top: 8px;
 | 
				
			||||||
 | 
					    margin-left: 8px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.title {
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    color:#fff;
 | 
				
			||||||
 | 
					    font-size: 30pt;
 | 
				
			||||||
 | 
					    font-family:"Roboto", bold, sans-serif;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.title2 {
 | 
				
			||||||
 | 
					    margin-top: 20px;
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    color:#fff;
 | 
				
			||||||
 | 
					    font-size: 20pt;
 | 
				
			||||||
 | 
					    font-family:"Roboto", bold, sans-serif;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.box-dark{
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    margin: auto;
 | 
				
			||||||
 | 
					    width: calc(100% - 50px);
 | 
				
			||||||
 | 
					    max-width: 600px;
 | 
				
			||||||
 | 
					    background-color: #1f262b;
 | 
				
			||||||
 | 
					    box-shadow: 3px 3px 10px #333;
 | 
				
			||||||
 | 
					    border: 2px solid #fff;
 | 
				
			||||||
 | 
					    border-radius: 10px;
 | 
				
			||||||
 | 
					    color: #fff;
 | 
				
			||||||
 | 
					    font-size: 15pt;
 | 
				
			||||||
 | 
					    font-family:"Roboto", regular, sans-serif;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.error{
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    bottom: 1rem;
 | 
				
			||||||
 | 
					    left: 1rem;
 | 
				
			||||||
 | 
					    height: 10rem;
 | 
				
			||||||
 | 
					    width: 16rem;
 | 
				
			||||||
 | 
					    background-color: #E53935;
 | 
				
			||||||
 | 
					    border-radius: 15px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#short-btn {
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    width: 10rem;
 | 
				
			||||||
 | 
					    margin-left: calc(50% - 5rem);
 | 
				
			||||||
 | 
					    margin-top: 20px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#copy-btn {
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    width: 10rem;
 | 
				
			||||||
 | 
					    margin-left: calc(50% - 5rem);
 | 
				
			||||||
 | 
					    margin-top: 1rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#surl-popup{
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    width: 30rem;
 | 
				
			||||||
 | 
					    height: 14rem;
 | 
				
			||||||
 | 
					    left: calc(50% - 15rem);
 | 
				
			||||||
 | 
					    top: calc(50% - 7rem);
 | 
				
			||||||
 | 
					    display: none;
 | 
				
			||||||
 | 
					    animation: slide-from-top alternate 0.4s;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#error-box{
 | 
				
			||||||
 | 
					    display: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@keyframes slide-from-top{
 | 
				
			||||||
 | 
					     from{top:20%;opacity: 0}
 | 
				
			||||||
 | 
					     to{top:calc(50% - 7rem);opacity: 1}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					@keyframes slide-from-left{
 | 
				
			||||||
 | 
					    from{left:-30rem;opacity: 0}
 | 
				
			||||||
 | 
					    to{left:1rem;opacity: 1}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media (max-width: 35rem){
 | 
				
			||||||
 | 
					    div.input-box {
 | 
				
			||||||
 | 
					        left: 5%;
 | 
				
			||||||
 | 
					        width: 90%;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    .error{
 | 
				
			||||||
 | 
					        bottom: 1rem;
 | 
				
			||||||
 | 
					        left: 1rem;
 | 
				
			||||||
 | 
					        height: 8rem;
 | 
				
			||||||
 | 
					        width: calc(100% - 2rem);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    #surl-popup{
 | 
				
			||||||
 | 
					        width: calc(100% - 2rem);
 | 
				
			||||||
 | 
					        height: 14rem;
 | 
				
			||||||
 | 
					        left: 1rem;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								public/sym/ic_close_white_24px.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								public/sym/ic_close_white_24px.svg
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
 | 
				
			||||||
 | 
					    <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
 | 
				
			||||||
 | 
					    <path d="M0 0h24v24H0z" fill="none"/>
 | 
				
			||||||
 | 
					</svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 265 B  | 
							
								
								
									
										32
									
								
								public/sym/script.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								public/sym/script.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					function selected(id){
 | 
				
			||||||
 | 
					    var element = document.getElementById(id);
 | 
				
			||||||
 | 
					    element.style.boxShadow = '1px 1px 2px #999';
 | 
				
			||||||
 | 
					    element.style.backgroundColor = "#ffffff";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var element = document.getElementById(id+'-input');
 | 
				
			||||||
 | 
					    element.style.color = "#000000";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					function deselected(id){
 | 
				
			||||||
 | 
					    var element = document.getElementById(id);
 | 
				
			||||||
 | 
					    element.style.boxShadow = '0px 0px 0px #999';
 | 
				
			||||||
 | 
					    element.style.backgroundColor = "#14181b";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var element = document.getElementById(id+'-input');
 | 
				
			||||||
 | 
					    element.style.color = "#ffffff";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function visible(id, status){
 | 
				
			||||||
 | 
					  if(status == "on"){
 | 
				
			||||||
 | 
					    document.getElementById(id).style.display = 'block';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else{
 | 
				
			||||||
 | 
					    document.getElementById(id).style.display = 'none';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function session_end() {
 | 
				
			||||||
 | 
					  if (confirm("Session timed out! Please login.")) {
 | 
				
			||||||
 | 
					    window.location.replace('https://adb.sh/robo-remote/login.php');
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										113
									
								
								server.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								server.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,113 @@
 | 
				
			|||||||
 | 
					const http = require('http')
 | 
				
			||||||
 | 
					const url = require('url')
 | 
				
			||||||
 | 
					const fs = require('fs')
 | 
				
			||||||
 | 
					const ws = require('ws')
 | 
				
			||||||
 | 
					const redis = require('redis')
 | 
				
			||||||
 | 
					const mime = require('mime')
 | 
				
			||||||
 | 
					const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const host = 'http://127.0.0.1:8080/'
 | 
				
			||||||
 | 
					const outpath = ['sym', '', 'manifest.json', 'admin', 'stats', 'analytics']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let led1_status = 'off';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//redis client
 | 
				
			||||||
 | 
					const redis_cli = redis.createClient({
 | 
				
			||||||
 | 
					    host: '127.0.0.1',
 | 
				
			||||||
 | 
					    port: 6379
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					redis_cli.on("error", function (error) {
 | 
				
			||||||
 | 
					    console.error(error)
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//HTTP server
 | 
				
			||||||
 | 
					http.createServer(function (req, res) {
 | 
				
			||||||
 | 
					    const q = url.parse(req.url, true);
 | 
				
			||||||
 | 
					    let filename = "./public" + q.pathname;
 | 
				
			||||||
 | 
					    let path_split = q.pathname.split("/", 3);
 | 
				
			||||||
 | 
					    if (path_split[path_split.length - 1] === "") filename += "/index.html";
 | 
				
			||||||
 | 
					    let file_type = mime.getType(filename)
 | 
				
			||||||
 | 
					    if (path_split[1] === "connect") {
 | 
				
			||||||
 | 
					        res.writeHead(200, {'Content-Type': file_type});
 | 
				
			||||||
 | 
					        res.write("");
 | 
				
			||||||
 | 
					        return res.end();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fs.readFile(filename, function(err, data) {
 | 
				
			||||||
 | 
					        if (err) {
 | 
				
			||||||
 | 
					            res.writeHead(404, {'Content-Type': "text/html"});
 | 
				
			||||||
 | 
					            return res.end("404 Not Found");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        res.writeHead(200, {'Content-Type': file_type});
 | 
				
			||||||
 | 
					        res.write(data);
 | 
				
			||||||
 | 
					        return res.end();
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}).listen(8080);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//WS server
 | 
				
			||||||
 | 
					const wss = new ws.Server({
 | 
				
			||||||
 | 
					    port: 8081,
 | 
				
			||||||
 | 
					    perMessageDeflate: {
 | 
				
			||||||
 | 
					        zlibDeflateOptions: {
 | 
				
			||||||
 | 
					            // See zlib defaults.
 | 
				
			||||||
 | 
					            chunkSize: 1024,
 | 
				
			||||||
 | 
					            memLevel: 7,
 | 
				
			||||||
 | 
					            level: 3
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        zlibInflateOptions: {
 | 
				
			||||||
 | 
					            chunkSize: 10 * 1024
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        // Other options settable:
 | 
				
			||||||
 | 
					        clientNoContextTakeover: true, // Defaults to negotiated value.
 | 
				
			||||||
 | 
					        serverNoContextTakeover: true, // Defaults to negotiated value.
 | 
				
			||||||
 | 
					        serverMaxWindowBits: 10, // Defaults to negotiated value.
 | 
				
			||||||
 | 
					        // Below options specified as default values.
 | 
				
			||||||
 | 
					        concurrencyLimit: 10, // Limits zlib concurrency for perf.
 | 
				
			||||||
 | 
					        threshold: 1024 // Size (in bytes) below which messages
 | 
				
			||||||
 | 
					        // should not be compressed.
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//WS handler
 | 
				
			||||||
 | 
					wss.on('connection', ws => {
 | 
				
			||||||
 | 
					    ws.on('message', message => {
 | 
				
			||||||
 | 
					        console.log(`Received message => ${message}`)
 | 
				
			||||||
 | 
					        let msg = message.split(";", 2)
 | 
				
			||||||
 | 
					        if (msg[0] === 'led1') {
 | 
				
			||||||
 | 
					            if (msg[1] === '') ws.send('error;try again')
 | 
				
			||||||
 | 
					            else if (msg[1] === 'on' || msg[1] === "off"){
 | 
				
			||||||
 | 
					                let xhr = new XMLHttpRequest();
 | 
				
			||||||
 | 
					                xhr.onreadystatechange = function() {
 | 
				
			||||||
 | 
					                    if (xhr.readyState === 4 && xhr.status === 200) {
 | 
				
			||||||
 | 
					                        wss.clients.forEach(clients => {
 | 
				
			||||||
 | 
					                            clients.send(message)
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                        led1_status = msg[1]
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                xhr.open('GET', `http://192.168.1.210/${msg[1]}`, true);
 | 
				
			||||||
 | 
					                xhr.timeout = 1000;
 | 
				
			||||||
 | 
					                xhr.ontimeout = function(e) {ws.send('error;device "led1" is offline')}
 | 
				
			||||||
 | 
					                xhr.send();
 | 
				
			||||||
 | 
					                setTimeout(to => {if (xhr.readyState !== 4) ws.send('error;device "led1" took too long to reach');xhr.abort()}, 1500)
 | 
				
			||||||
 | 
					            }else ws.send('error;try again')
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    ws.send('websocket connected')
 | 
				
			||||||
 | 
					    ws.send(`led1;${led1_status}`)
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//random key
 | 
				
			||||||
 | 
					function get_key(length) {
 | 
				
			||||||
 | 
					    let forbidden = false; let output = ''
 | 
				
			||||||
 | 
					    let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
 | 
				
			||||||
 | 
					    do{
 | 
				
			||||||
 | 
					        for (let i = 0; i < length; i++ )
 | 
				
			||||||
 | 
					            output += characters.charAt(Math.floor(Math.random() * characters.length))
 | 
				
			||||||
 | 
					        for (let i = 0; i < output.length; i++) if (output === outpath[i]) forbidden = true
 | 
				
			||||||
 | 
					        redis_cli.hget("surl;"+output, "url", function(err, obj) {
 | 
				
			||||||
 | 
					            if(err) console.log(err)
 | 
				
			||||||
 | 
					            if(obj) forbidden = true
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    } while (forbidden)
 | 
				
			||||||
 | 
					    return output
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user