whois.handle: SIS-80-8-3-13
whois.name: AT&T Enterprises, LLC
whois.cidrs: 162.192.0.0/12
whois.created: 2013-03-01T00:00:00.000000
whois.updated: 2024-12-05T00:00:00.000000
whois.allocation_type: ALLOCATION
whois.handle: AEL-360
whois.name: AT&T Enterprises, LLC
whois.street: 208 S. Akard St.
whois.city: Dallas
whois.state: TX
whois.postal_code: 75202
whois.country: US
whois.handle: ABUSE7-ARIN
whois.name: abuse
whois.email: abuse@att.net
whois.handle: ZS44-ARIN
whois.name: IPAdmin-ATT Internet Services
whois.email: ipadmin@att.com
whois.handle: ICC-ARIN
whois.name: IP Team
whois.email: rm-ipspecialist@att.com
whois.handle: ZS44-ARIN
whois.name: IPAdmin-ATT Internet Services
whois.email: ipadmin@att.com
services.protocol: SSH
services.transport_protocol: TCP
services.scan_time: 2025-07-28T08:32:21.853698
services.banner: SSH-2.0-OpenSSH_7.8
services.source: OSI_APPLICATION_LAYER
services.part: a
services.vendor: OpenBSD
services.product: OpenSSH
services.version: 7.8
services.cpe: cpe:2.3:a:openbsd:openssh:7.8:*:*:*:*:*:*:*
services.value: remote-access
services.raw: SSH-2.0-OpenSSH_7.8
services.protocol_version: 2.0
services.software_version: OpenSSH_7.8
services.kex_algorithms: curve25519-sha256 curve25519-sha256@libssh.org ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 diffie-hellman-group-exchange-sha256 diffie-hellman-group16-sha512 diffie-hellman-group18-sha512 diffie-hellman-group14-sha256 diffie-hellman-group14-sha1
services.host_key_algorithms: rsa-sha2-512 rsa-sha2-256 ssh-rsa ecdsa-sha2-nistp256
services.client_to_server_ciphers: chacha20-poly1305@openssh.com aes128-ctr aes192-ctr aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com
services.server_to_client_ciphers: chacha20-poly1305@openssh.com aes128-ctr aes192-ctr aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com
services.client_to_server_macs: umac-64-etm@openssh.com umac-128-etm@openssh.com hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com hmac-sha1-etm@openssh.com umac-64@openssh.com umac-128@openssh.com hmac-sha2-256 hmac-sha2-512 hmac-sha1
services.server_to_client_macs: umac-64-etm@openssh.com umac-128-etm@openssh.com hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com hmac-sha1-etm@openssh.com umac-64@openssh.com umac-128@openssh.com hmac-sha2-256 hmac-sha2-512 hmac-sha1
services.client_to_server_compression: none zlib@openssh.com
services.server_to_client_compression: none zlib@openssh.com
services.kex_algorithm: curve25519-sha256@libssh.org
services.host_key_algorithm: ecdsa-sha2-nistp256
services.cipher: aes128-ctr
services.mac: hmac-sha2-256
services.compression: none
services.cipher: aes128-ctr
services.mac: hmac-sha2-256
services.compression: none
services.curve: P-256
services.hassh_fingerprint: b12d2871a1189eff20364cf5333619ee
services.protocol: HTTP
services.transport_protocol: TCP
services.scan_time: 2025-07-28T03:25:41.194733
services.banner: HTTP/1.1 200 OK
  cache-control: max-age=0
  content-type: text/html; charset=UTF-8
  etag: W/"12db8-ZMAE6fMNacVACUD3v+9PlAP2Cc2"
  last-modified: Tue, 27 Aug 2024 00:14:12 GMT
  vary: Accept-Encoding
  content-encoding: gzip
  content-length: 17838
  date:  <REDACTED>
  
services.source: OSI_TRANSPORT_LAYER
services.part: o
services.product: linux
services.cpe: cpe:2.3:o:*:linux:*:*:*:*:*:*:*:*
services.value: bootstrap
services.value: jquery
services.value: network.device.web-ui
services.path: /
services.endpoint_type: HTTP
services.scan_time: 2025-07-28T03:25:41.194733
services.uri: http://162.204.10.214/
services.protocol: HTTP/1.1
services.status_reason: OK
services.key: etag
services.headers: W/"12db8-ZMAE6fMNacVACUD3v+9PlAP2Cc2"
services.key: cache-control
services.headers: max-age=0
services.key: content-length
services.headers: 17838
services.key: last-modified
services.headers: Tue, 27 Aug 2024 00:14:12 GMT
services.key: date
services.headers: <REDACTED>
services.key: content-type
services.headers: text/html; charset=UTF-8
services.key: vary
services.headers: Accept-Encoding
services.key: content-encoding
services.headers: gzip
services.html_tags: <title>Settings</title> <meta name="viewport" content="width=device-width, initial-scale=1.0">
services.body: <!DOCTYPE html>
  <html>
  <head>
      <title>Settings</title>
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
      <link rel="stylesheet" href="assets/css/bootstrap-3.3.6.min.css">
      <link rel="stylesheet" href="assets/css/bootstrap-theme-3.3.6.min.css">
      <script src="assets/js/jquery-2.1.4.min.js"></script>
      <script src="assets/js/bootstrap-3.3.6.min.js"></script>
  <style>
  
  html, button, input, select, textarea {
      font-family: Helvetica Neue,Helvetica,Arial,sans-serif;
      font-weight: 200;
  }
  
  h1 { font-weight: 400; }
  h2 { font-weight: 400; }
  h3 { font-weight: 400; }
  h4 { font-weight: 400; }
  h5 { font-weight: 400; }
  
  .scan_row {
      height: 3em;
      vertical-align: middle;
  }
  .scan_ssid {
      font-size: 1.3em;
      display: inline-block;
  }
  .scan_ssid_lock {
      margin-right: 0.5em;
      font-size: 1.8em;
      margin-top: .18em;
  }
  
  .main_area {
      display: none;
  }
  
  #allbodyloading {
      width: 100%;
      height: 100%;
      padding-top: 100px;
      text-align: center;
  }
  .sk-cube-grid {
    width: 40px;
    height: 40px;
    margin: 100px auto;
  }
  
  .sk-cube-grid .sk-cube {
    width: 33%;
    height: 33%;
    background-color: #333;
    float: left;
    -webkit-animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
            animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out; 
  }
  .sk-cube-grid .sk-cube1 {
    -webkit-animation-delay: 0.2s;
            animation-delay: 0.2s; }
  .sk-cube-grid .sk-cube2 {
    -webkit-animation-delay: 0.3s;
            animation-delay: 0.3s; }
  .sk-cube-grid .sk-cube3 {
    -webkit-animation-delay: 0.4s;
            animation-delay: 0.4s; }
  .sk-cube-grid .sk-cube4 {
    -webkit-animation-delay: 0.1s;
            animation-delay: 0.1s; }
  .sk-cube-grid .sk-cube5 {
    -webkit-animation-delay: 0.2s;
            animation-delay: 0.2s; }
  .sk-cube-grid .sk-cube6 {
    -webkit-animation-delay: 0.3s;
            animation-delay: 0.3s; }
  .sk-cube-grid .sk-cube7 {
    -webkit-animation-delay: 0s;
            animation-delay: 0s; }
  .sk-cube-grid .sk-cube8 {
    -webkit-animation-delay: 0.1s;
            animation-delay: 0.1s; }
  .sk-cube-grid .sk-cube9 {
    -webkit-animation-delay: 0.2s;
            animation-delay: 0.2s; }
  
  @-webkit-keyframes sk-cubeGridScaleDelay {
    0%, 70%, 100% {
      -webkit-transform: scale3D(1, 1, 1);
              transform: scale3D(1, 1, 1);
    } 35% {
      -webkit-transform: scale3D(0, 0, 1);
              transform: scale3D(0, 0, 1); 
    }
  }
  
  @keyframes sk-cubeGridScaleDelay {
    0%, 70%, 100% {
      -webkit-transform: scale3D(1, 1, 1);
              transform: scale3D(1, 1, 1);
    } 35% {
      -webkit-transform: scale3D(0, 0, 1);
              transform: scale3D(0, 0, 1);
    } 
  }
  
  .spin {
    -webkit-animation: spin 1s infinite linear;
    -moz-animation: spin 1s infinite linear;
    -o-animation: spin 1s infinite linear;
    animation: spin 1s infinite linear;
  
    -webkit-transform-origin: 50% 50%;
    -moz-transform-origin: 50% 50%;
    -ms-transform-origin:50% 50%; /* IE 9 */
    transform-origin:50% 50%;
  
    display: none;
  }
  
  @-moz-keyframes spin {
    from {
      -moz-transform: rotate(0deg);
    }
    to {
      -moz-transform: rotate(360deg);
    }
  }
  
  @-webkit-keyframes spin {
    from {
      -webkit-transform: rotate(0deg);
    }
    to {
      -webkit-transform: rotate(360deg);
    }
  }
  
  @keyframes spin {
    from {
      transform: rotate(0deg);
    }
    to {
      transform: rotate(360deg);
    }
  }
  
  #main_error {
      display: none;
      width:   100%;
      height:  300px;
  }
  #main_error_text {
      margin-left:  auto;
      margin-right: auto;
      width:        400px;
      margin-top:   120px;
  }
  .statusheader {
      font-size: 1.2em;
      font-weight: 700;
  }
  
  nav .pagetitle {
      line-height: 50px;
      display: inline-block;
      padding: 0px;
      font-size: 2.0em;
      vertical-align:middle;
  }
  .pagesubtitle {
      font-size: 1.2em;
      margin-top: -5px;
      margin-left: 5px;
  }
  
  </style>
  </head>
  
  <body>
  
  <div id='allbodyloading'>
      <div class="sk-cube-grid">
      <div class="sk-cube sk-cube1"></div>
      <div class="sk-cube sk-cube2"></div>
      <div class="sk-cube sk-cube3"></div>
      <div class="sk-cube sk-cube4"></div>
      <div class="sk-cube sk-cube5"></div>
      <div class="sk-cube sk-cube6"></div>
      <div class="sk-cube sk-cube7"></div>
      <div class="sk-cube sk-cube8"></div>
      <div class="sk-cube sk-cube9"></div>
      </div>
  </div>
  
  <div id='main_error'>
      <div id='main_error_text' class="alert alert-danger"></div>
  </div>
  
  <nav class='main_area' style='position: fixed; z-index: 10; top: 0; height: 73px; width: 100%; background: #fff; border-bottom: solid 1px #bbb;'>
      <div class="container">
          <div class='row'>
              <div class='col-xs-12'>
                  <img src='/webconfiglogo.png' class="logo" style='height: 50px;'></img>
                  <div class="btn-group pull-right" style='margin-top: 10px;'>
                      <button type="button" class="btn btn-danger dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style='height: 30px; margin-top: 10px;'>
                          <span class='glyphicon glyphicon-off'></span>&nbsp;&nbsp;<span class="caret"></span>
                      </button>
                      <ul class="dropdown-menu">
                          <li><a class='action_reboot' href="#">Reboot</a></li>
                          <li><a class='action_poweroff' href="#">Power Off</a></li>
                      </ul>
                  </div>
                  <div class='pagesubtitle'>
                      <span class='modelname'>Model</span>
                  </div>
              </div>
          </div>
      </div>
  </nav>
  
  <div class='main_area container' style='padding-top: 90px; margin-top: 0;'>
      <h3>System Status</h3>
      <h6>Serial #<span id='deviceserial'</span>></h6>
      <div class='row'>
          <div class='col-sm-6' style='margin-top: 20px; min-height: 100px;'>
              <div class='statusheader'>Operating System</div>
              <div style='width: 290px;'>
                  <button class="btn btn-primary action_reinstall" style='min-width: 110px; float: right; line-height: 15px;'>Reinstall</button>
                  <div style='font-size: 1.5em;' class='firmware_status text-success'>&nbsp;</div>
              </div>
              <div style='font-size: 1.0em;' class='firmware_description'>&nbsp;</div>
          </div>
  
          <div class='col-sm-6 vendorsoftwarearea' style='margin-top: 20px; min-height: 100px;'>
              <div class='statusheader'><span class='vendorname'>Manufacturer</span> Software</div>
              <div style='width: 290px;'>
                  <button class="btn btn-primary action_restartvendorsoftware case_vendoraction case_vendorsoftwarenotrunning" style='min-width: 110px; float: right; line-height: 15px;'>Start</button>
                  <div class="btn-group case_vendoraction case_vendorsoftwarerunning" style='min-width: 110px; float: right;'>
                      <button type="button" class="btn btn-primary action_restartvendorsoftware" style='min-width: 85px; line-height: 15px;'>Restart</button>
                      <button type="button" class="btn btn-primary dropdown-toggle" style=' line-height: 15px; ' data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                          <span class="caret"></span>
                          <span class="sr-only">Toggle Dropdown</span>
                      </button>
                      <ul class="dropdown-menu dropdown-menu-right">
                          <li><a class='action_stopvendorsoftware' href="#">Stop</a></li>
                      </ul>
                  </div>
                  <div style='font-size: 1.5em;' class='vendorsoftware_status'>&nbsp;</div>
              </div>
              <div style='font-size: 1.0em;' class='vendorsoftware_description'>&nbsp;</div>
          </div>
  
          <div class='col-sm-6 softwarearea' style='margin-top: 20px; min-height: 100px;'>
              <div class='statusheader'>Roon Server Software</div>
              <div style='width: 290px;'>
                  <button class="btn btn-primary action_restartsoftware case_softwarenotrunning" style='min-width: 110px; float: right; line-height: 15px;'>Start</button>
                  <button class="btn btn-primary action_missingcodecs case_missingcodecs" style='min-width: 110px; float: right; line-height: 15px;'>?</button>
                  <div class="btn-group case_softwarerunning" style='min-width: 110px; float: right;'>
                      <button type="button" class="btn btn-primary action_restartsoftware" style='min-width: 85px; line-height: 15px;'>Restart</button>
                      <button type="button" class="btn btn-primary dropdown-toggle" style='line-height: 15px; ' data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                          <span class="caret"></span>
                          <span class="sr-only">Toggle Dropdown</span>
                      </button>
                      <ul class="dropdown-menu dropdown-menu-right">
                          <li><a class='action_stopsoftware' href="#">Stop</a></li>
                      </ul>
                  </div>
                  <div style='font-size: 1.5em;' class='software_status'>&nbsp;</div>
              </div>
              <div style='font-size: 1.0em;' class='software_description'>&nbsp;</div>
          </div>
  
          <div class='col-sm-6 cdarea' style='margin-top: 20px; min-height: 100px;'>
              <div class='statusheader'>CD Ripper</div>
              <div style='width: 290px;'>
                  <button class="btn btn-primary action_cdhelp" style='float: right; line-height: 15px;'>?</button><div style='float: right; line-height: 15px;'>&nbsp;</div><button class="btn btn-primary action_cdeject" style='min-width: 110px; float: right; line-height: 15px;'>Eject</button>
                  <div style='font-size: 1.5em;' class='cd_status'>&nbsp;</div>
              </div>
              <div style='font-size: 1.0em;' class='cd_description'>&nbsp;</div>
          </div>
  
          <div class='col-sm-6' style='margin-top: 20px; min-height: 100px;'>
              <div class='statusheader'>Roon Database &amp; Settings</div>
              <div style='width: 290px;'>
                  <button class="btn btn-primary action_delete" style='min-width: 110px; float: right; line-height: 15px;'>Reset</button>
                  <div style='font-size: 1.5em;' class='data_status'>&nbsp;</div>
              </div>
              <div style='font-size: 1.0em;' class='data_description'>&nbsp;</div>
          </div>
  
          <div class='col-sm-6 internalstoragearea' style='margin-top: 20px; min-height: 100px;'>
              <div class='statusheader'>Internal Music Storage</div>
              <div style='width: 290px;'>
                  <button class="btn btn-primary action_format" style='min-width: 110px; float: right; line-height: 15px;'>Format</button>
                  <div style='font-size: 1.5em;' class='internalstorage_status'>&nbsp;</div>
              </div>
              <div style='font-size: 1.0em; margin-top:0.7em; white-space: pre-wrap;' class='internalstorage_description'>&nbsp;</div>
          </div>
  
          <div class='col-sm-6' style='margin-top: 20px; min-height: 100px;'>
              <div class='statusheader'>Tailscale</div>
              <div style='width: 290px;'>
                  <button class="btn btn-primary action_show_tailscale" style='min-width: 110px; float: right; line-height: 15px;'>Sign in</button>
                  <button class="btn btn-primary action_logout_tailscale" style='min-width: 110px; float: right; line-height: 15px;'>Logout</button>
                  <div style='font-size: 1.5em;' class='tailscale_status'>&nbsp;</div>
                  <div style='font-size: 0.8em; font-weight: 400; font-style: italic; margin-left: 1px;' class='tailscale_username'>&nbsp;</div>
              </div>
              <div style='font-size: 1.0em; margin-top:0.7em; white-space: pre-wrap;' class='tailscale_description'><p>Tailscale is an app that creates a private, secure connection between your phone and your Roon Server, making it easier to stay connected even when you're away from home. If you've been having trouble with ARC due to your internet provider or home network, Tailscale could be a great solution. <a href='https://roon.link/RoonOS/tailscaleinfo'>Learn more</a></p></div>
          </div>
      </div>
  
      <h3 class=''>Networking</h3>
      <div>
          <!-- Nav tabs -->
          <ul class="nav nav-tabs" id='interfaces_tabs'>
          </ul>
  
          <!-- Tab panes -->
          <div class="tab-content" id='interfaces_pages'>
          </div>
  
      </div>
  
      <div class='interface_template' style='display: none; padding-top: 1em;'>
          <p class='wifisettings text-warning' style='margin: 1em 0; font-size: 1.3em;'>NOTE: Ethernet is more reliable for audio transmission, WiFi should only be used for control.</p>
  
          <form>
              <p>
              <div class="form-group enableinterface" style='width: 175px; display: inline-block; padding-right: 10px;'>
                  <label class='control-label' for="ip">Network Interface</label><br>
                  <div class="btn-group" data-toggle="buttons">
                      <label class="btn btn-default active">
                          <input type="radio" name="enablement" class="config_enabled" value='enabled' autocomplete="off" checked> Enabled
                      </label>
                      <label class="btn btn-default">
                          <input type="radio" name="enablement" class="config_disabled" value='disabled' autocomplete="off"> Disabled
                      </label>
                  </div>
              </div>
              <p>
              <div class='allsettings'>
                  <div class='row wifisettings'>
                      <div class="form-group col-sm-6">
                          <label class='control-label' for="ip">WiFi SSID</label>
                          <input type="text" class="form-control config_ssid">
                      </div>
                      <div class="form-group col-sm-6">
                          <label class='control-label'>&nbsp;</label><br>
                          <button data-toggle="modal" data-target="#wifi_scan_modal" class='wifi_scan_button btn btn-default' style='width: 100%; margin-bottom: 2px;'>Scan WiFi Networks</button>
                      </div>
                      <div class="form-group col-sm-6">
                          <label class='control-label' for="ip">WiFi Security</label><br>
                          <div class="btn-group" style='margin-bottom: 2px;'>
                              <button type="button" class="btn btn-default dropdown-toggle config_security" data-toggle="dropdown" style='min-width:145px'>
                                  <div class='title'>None</div> <span class="caret" style="position: absolute; left: 90%; top: 45%;"></span>
                              </button>
                              <ul class="dropdown-menu">
                                  <li><a class='wifi_security_wpa2' href="#">WPA2 (PSK)</a></li>
                                  <li><a class='wifi_security_wpa'  href="#">WPA (PSK)</a></li>
                                  <li><a class='wifi_security_wep'  href="#">WEP</a></li>
                                  <li><a class='wifi_security_none' href="#">None</a></li>
                              </ul>
                          </div>
                      </div>
                      <div class="form-group col-sm-6">
                          <label class='control-label' for="ip">WiFi Password</label>
                          <input type="password" class="form-control config_passphrase">
                      </div>
                  </div>
  
                  <div class="form-group">
                      <label>IP Address Setup</label>
                      <br>
                      <div class="btn-group" data-toggle="buttons">
                          <label class="btn btn-default active">
                              <input type="radio" name="staticip" class="config_dhcp" value='dhcp' autocomplete="off" checked> DHCP
                          </label>
                          <label class="btn btn-default">
                              <input type="radio" name="staticip" class="config_staticip" value='staticip' autocomplete="off"> Static IP
                          </label>
                      </div>
                  </div>
  
                  <div class='row' style='margin-bottom: 2em;'>
                      <div class="form-group col-sm-6">
                          <label class='control-label' for="ip">IP Address</label>
                          <input type="text" class="form-control config_ip" placeholder="0.0.0.0">
                      </div>
                      <div class="form-group col-sm-6">
                          <label class='control-label' for="netmask">Netmask</label>
                          <input type="text" class="form-control config_netmask" placeholder="0.0.0.0">
                      </div>
                      <div class="form-group col-sm-6">
                          <label class='control-label' for="gateway">Gateway</label>
                          <input type="text" class="form-control config_gateway" placeholder="0.0.0.0">
                      </div>
                      <div class="form-group col-sm-6">
                          <label class='control-label' for="dns">DNS Server</label>
                          <input type="text" class="form-control config_dns" placeholder="0.0.0.0">
                      </div>
                  </div>
              </div>
          </form>
      </div>
  
      <div style='padding-top: 40px; padding-bottom: 100px; border-top: solid 1px #ddd;'>
          <div class="collapse alert alert-danger alert-dismissible saveerrors" style='margin: 10px 0;'>
              <button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
              <ul></ul>
          </div>
          <button class="btn btn-primary savebutton pull-right" style='padding-right: 5em; padding-left: 5em;'>
              <span class="text" style='display: inline-block; margin: 0 20px;'>Save</span>
              <span class="glyphicon glyphicon-refresh spin"></span>
          </button>
      </div>
  
      <div class="modal" id="working_modal" tabindex="-1">
          <div class="modal-dialog">
              <div class="modal-content">
                  <div class="modal-header">
                      <h4 class="modal-title title"></h4>
                  </div>
                  <div class="modal-body">
                      <div class="sk-cube-grid spinner">
                      <div class="sk-cube sk-cube1"></div>
                      <div class="sk-cube sk-cube2"></div>
                      <div class="sk-cube sk-cube3"></div>
                      <div class="sk-cube sk-cube4"></div>
                      <div class="sk-cube sk-cube5"></div>
                      <div class="sk-cube sk-cube6"></div>
                      <div class="sk-cube sk-cube7"></div>
                      <div class="sk-cube sk-cube8"></div>
                      <div class="sk-cube sk-cube9"></div>
                      </div>
                      <div class='text'>
                      </div>
                  </div>
              </div>
          </div>
      </div>
  
      <div class="modal" id="wifi_scan_modal" tabindex="-1">
          <div class="modal-dialog">
              <div class="modal-content">
                  <div class="modal-header">
                      <h4 class="modal-title" id="wifi_scan_modal_title"></h4>
                  </div>
                  <div class="modal-body">
                  </div>
                  <div class="modal-footer">
                      <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
                  </div>
              </div>
          </div>
      </div>
  
      <div class="modal" id="tailscale_modal" tabindex="-1">
          <div class="modal-dialog">
              <div class="modal-content">
                  <div class="modal-header">
                      <h4 class="modal-title">Enable Tailscale</h4>
                  </div>
                  <div class="modal-body">
                      <p>Sign into Tailscale to create a private, secure
                      connection between your phone and your Roon Server, making
                      it easier to stay connected even when you're away from
                      home.</p>
  
                      <p>
                      To use Tailscale to connect your phone with this machine, you will need to do the following steps:
                      <li>Create a free Tailscale account
                      </li>
                      <li>Install the Tailscale app on your phone, and sign in
                      </li>
                      <li>Connect this machine to Tailscale by clicking below
                      </li>
                      </p>
  
                      <div style="text-align: center;">
                          <button type="button" class="btn btn-primary action_login_tailscale">Sign in to Tailscale</button>
                          <br>
                          <i style='font-size: 0.8em;'>this will open Tailscale signin page in a new tab</i>
                      </div>
                  </div>
                  <div class="modal-footer">
                      <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
                  </div>
              </div>
          </div>
      </div>
  
      <div class="modal" id="wifi_key_modal" tabindex="-1">
          <form>
              <div class="modal-dialog modal-sm">
                  <div class="modal-content">
                      <div class="modal-header">
                          <h4 class="modal-title">Enter WiFi Password</h4>
                      </div>
                      <div class="modal-body">
                          <div class="form-group">
                              <label class='control-label'>WiFi SSID</label>
                              <input type="text" class="form-control input_ssid" readonly>
                          </div>
                          <div class="form-group">
                              <label class='control-label'>WiFi Password</label>
                              <input type="password" class="form-control input_passphrase">
                          </div>
                      </div>
                      <div class="modal-footer">
                          <button type="submit" class="btn btn-default">OK</button>
                          <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
                      </div>
                  </div>
              </div>
          </form>
      </div>
      <div class="modal" id="confirm_modal" tabindex="-1">
          <form>
              <div class="modal-dialog modal-sm">
                  <div class="modal-content">
                      <div class="modal-header">
                          <h4 class="modal-title title"></h4>
                      </div>
                      <div class="modal-body">
                          <div class='text'></div>
                      </div>
                      <div class="modal-footer">
                          <button type="submit" class="btn btn-default ok">OK</button>
                          <button type="button" class="btn btn-default cancel" data-dismiss="modal">Cancel</button>
                      </div>
                  </div>
              </div>
          </form>
      </div>
      <div class="modal" id="message_modal" tabindex="-1">
          <form>
              <div class="modal-dialog modal-sm">
                  <div class="modal-content">
                      <div class="modal-header">
                          <h4 class="modal-title title"></h4>
                      </div>
                      <div class="modal-body">
                          <div class='text'></div>
                      </div>
                      <div class="modal-footer">
                          <button type="submit" class="btn btn-default ok">OK</button>
                      </div>
                  </div>
              </div>
          </form>
      </div>
  </div>
  
  <script>
  $(function(){
      $("[data-hide]").on("click", function(){
          $(this).closest("." + $(this).attr("data-hide")).hide();
      });
      $("#message_modal .ok").on("click", function(event) {
                              event.preventDefault();
                              document.location.reload(true);
                          });
  });
  
  function message_modal(a) {
      $("#message_modal .title").text(a.title);
      if (a.text) $("#message_modal .text").text(a.text);
      if (a.html) $("#message_modal .text").html(a.html);
      $("#message_modal").modal('show');
  }
  function working_modal(a) {
      if (a.hidespinner)
          $("#working_modal .spinner").hide();
      else
          $("#working_modal .spinner").show();
      $("#working_modal .title").text(a.title);
      $("#working_modal .text").text(a.text);
      $("#working_modal").modal('show');
  }
  function working_modal_hide() {
      $("#working_modal").modal('hide');
  }
  
  var gd;
  var HttpRoot = "/";
  $.ajax({
      type: "POST",
      url: HttpRoot + "1/getstate",
      dataType: "json",
      data: { }
  })
  .done(function(data) {
      if (data.status == "Success") {
          gd = data;
          try {
              $(".vendorname").text(data.data.device_vendor);
              $(".modelname").text(data.data.device_model);
              $("#deviceserial").text(data.data.device_serial);
              document.title = data.data.device_vendor + " " + data.data.device_model;
  
              var sysnumdays    = Math.floor(data.data.state.uptime / 86400);
              var sysnumhours   = Math.floor((data.data.state.uptime % 86400) / 3600);
              var sysnumminutes = Math.floor(((data.data.state.uptime % 86400) % 3600) / 60);
              var sysnumseconds = ((data.data.state.uptime % 86400) % 3600) % 60;
  
              var roonnumdays    = 0;
              var roonnumhours   = 0;
              var roonnumminutes = 0;
              var roonnumseconds = 0;
  
              if (data.data.state.roon_uptime) {
                  var tt = data.data.state.roon_uptime.split(":");
                  roonnumseconds = tt.length >= 1 ? tt[tt.length-1]*1 : 0;
                  roonnumminutes = tt.length >= 2 ? tt[tt.length-2]*1 : 0;
                  roonnumhours   = tt.length >= 3 ? tt[tt.length-3]*1 : 0;
                  roonnumdays    = tt.length >= 4 ? tt[tt.length-4]*1 : 0;
                  while (roonnumseconds >= 60) {
                      roonnumseconds = roonnumseconds - 60;
                      roonnumminutes++;
                  }
                  while (roonnumminutes >= 60) {
                      roonnumminutes = roonnumminutes - 60;
                      roonnumhours++;
                  }
                  while (roonnumhours >= 24) {
                      roonnumhours = roonnumhours - 24;
                      roonnumdays++;
                  }
              }
  
              var vendornumdays    = 0;
              var vendornumhours   = 0;
              var vendornumminutes = 0;
              var vendornumseconds = 0;
  
              if (data.data.state.vendor_uptime) {
                  vendornumdays    = Math.floor(data.data.state.vendor_uptime / 86400);
                  vendornumhours   = Math.floor((data.data.state.vendor_uptime % 86400) / 3600);
                  vendornumminutes = Math.floor(((data.data.state.vendor_uptime % 86400) % 3600) / 60);
                  vendornumseconds = ((data.data.state.vendor_uptime % 86400) % 3600) % 60;
              }
  
              var sysuptime = "";
              var roonuptime = "";
              var vendoruptime = "";
  
              if (sysnumdays    > 0)  { if (sysuptime != "") sysuptime += ", "; sysuptime += sysnumdays    + " day"    + (sysnumdays    == 1 ? "" : "s"); }
              if (sysnumhours   > 0)  { if (sysuptime != "") sysuptime += ", "; sysuptime += sysnumhours   + " hour"   + (sysnumhours   == 1 ? "" : "s"); }
              if (sysnumminutes >= 0) { if (sysuptime != "") sysuptime += ", "; sysuptime += sysnumminutes + " minute" + (sysnumminutes == 1 ? "" : "s"); }
              if (sysnumseconds >= 0) { if (sysuptime != "") sysuptime += ", "; sysuptime += sysnumseconds + " second" + (sysnumseconds == 1 ? "" : "s"); }
  
              if (roonnumdays    > 0)  { if (roonuptime != "") roonuptime += ", "; roonuptime += roonnumdays    + " day"    + (roonnumdays    == 1 ? "" : "s"); }
              if (roonnumhours   > 0)  { if (roonuptime != "") roonuptime += ", "; roonuptime += roonnumhours   + " hour"   + (roonnumhours   == 1 ? "" : "s"); }
              if (roonnumminutes >= 0) { if (roonuptime != "") roonuptime += ", "; roonuptime += roonnumminutes + " minute" + (roonnumminutes == 1 ? "" : "s"); }
              if (roonnumseconds >= 0) { if (roonuptime != "") roonuptime += ", "; roonuptime += roonnumseconds + " second" + (roonnumseconds == 1 ? "" : "s"); }
  
              if (vendornumdays    > 0)  { if (vendoruptime != "") vendoruptime += ", "; vendoruptime += vendornumdays    + " day"    + (vendornumdays    == 1 ? "" : "s"); }
              if (vendornumhours   > 0)  { if (vendoruptime != "") vendoruptime += ", "; vendoruptime += vendornumhours   + " hour"   + (vendornumhours   == 1 ? "" : "s"); }
              if (vendornumminutes >= 0) { if (vendoruptime != "") vendoruptime += ", "; vendoruptime += vendornumminutes + " minute" + (vendornumminutes == 1 ? "" : "s"); }
              if (vendornumseconds >= 0) { if (vendoruptime != "") vendoruptime += ", "; vendoruptime += vendornumseconds + " second" + (vendornumseconds == 1 ? "" : "s"); }
  
              var str = "<div>Version " + data.data.device_display_version + "</div>";
              str += "<div>Running " + sysuptime + ".</div>";
              $(".firmware_description").html(str);
              $(".firmware_status").addClass("text-success").removeClass("text-danger");
              $(".firmware_status").html("OK");
  
              if (data.data.state.mounted_data && data.data.state.has_data) {
                  $(".data_status").addClass("text-success").removeClass("text-danger");
                  $(".data_status").text("OK");
                  var pct = (100*((data.data.state.data_total - data.data.state.data_used) / data.data.state.data_total)).toFixed(0);
                  str = pct + "% of " + (data.data.state.data_total / (1024 * 1024)).toFixed(0) + " GB available." ;
                  $(".data_description").html(str);
              } else {
                  $(".data_status").addClass("text-danger").removeClass("text-success");
                  $(".data_status").html("Not Ready");
                  $(".softwarearea").remove();
              }
  
              if (data.data.state.internal_storage) {
                  if (data.data.state.internal_storage.mounted) {
                      $(".internalstorage_status").text("OK");
                      $(".internalstorage_status").addClass("text-success").removeClass("text-danger");
                  } else {
                      $(".internalstorage_status").text("Not Ready");
                      $(".internalstorage_status").addClass("text-danger").removeClass("text-success");
                  }
                  var desc = data.data.state.internal_storage.info;
                  if (data.data.state.internal_storage.data_total > 0) {
                      var pct = (100*((data.data.state.internal_storage.data_total - data.data.state.internal_storage.data_used) / data.data.state.internal_storage.data_total)).toFixed(0);
                      desc += "\n" + pct + "% of " + (data.data.state.internal_storage.data_total / (1024 * 1024)).toFixed(0) + " GB available." ;
                  }
                  $(".internalstorage_description").text(desc);
              } else {
                  $(".internalstoragearea").remove();
              }
  
              if (data.data.state.cd) {
                  if (data.data.state.cd.status == "no_cd_rom") {
                      $(".cdarea").remove();
  		} else if (data.data.state.cd.status == "waiting") {
                      $(".cd_status").addClass("text-success").removeClass("text-danger");
                      $(".cd_status").html("OK");
                      $(".cd_description").html("Waiting for CD");
                  } else if (data.data.state.cd.status == "ripping") {
                      $(".cd_status").addClass("text-success").removeClass("text-danger");
                      $(".cd_status").html("Ripping");
                      $(".cd_description").html(data.data.state.cd.track_count + " track CD: Ripping track " + data.data.state.cd.track);
                  } else if (data.data.state.cd.status == "success") {
  
                      var dirinfo = "";
  
  
                      try {
                          var dir = data.data.state.cd.directory;
                          var drive = data.data.state.cd.drive.split('/');
                          drive = drive[drive.length-1];
  
                          var userAgent = window.navigator.userAgent;
                          var platform = window.navigator.platform;
                          var macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'];
                          var windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE'];
                          var iosPlatforms = ['iPhone', 'iPad', 'iPod'];
  
                          var link;
                          if (macosPlatforms.indexOf(platform) !== -1 || iosPlatforms.indexOf(platform) !== -1) {
                              link = "smb://" + window.location.hostname + "/Data/Storage/" + drive + "/" + data.data.state.cd.directory;
                              dirinfo = "<br>You can find the files <a href='" + link + "'>here</a>.";
                          } else {
                              link = "\\\\" + window.location.hostname + "\\Data\\Storage\\" + drive + "\\" + data.data.state.cd.directory;
                              dirinfo = "<br>You can find the files at:<br><input readonly type='text' onFocus='this.setSelectionRange(0, this.value.length)' data-gramm_editor='false' style='width: 100%;' value='" + link.replace(/\//g, "\\").replace(/'/, "&apos;") + "'>";
                          }
  
                      } catch (e) {
                      }
  
                      $(".cd_status").html("Success");
                      $(".cd_status").addClass("text-success").removeClass("text-danger");
                      $(".cd_description").html("Rip of your " + data.data.state.cd.track_count + " track CD was successfully completed at " + (new Date(1000 * Number(data.data.state.cd.stopped_at)).toLocaleString()) + "." + dirinfo); 
                  } else if (data.data.state.cd.status == "fail") {
                      $(".cd_status").addClass("text-danger").removeClass("text-success");
  
                      var s = data.data.state.cd.error;
                      var m;
  
                      if ((m=s.match(/already_ripped (.*)/))) {
                          $(".cd_status").html("Warning");
                          s = "This " + data.data.state.cd.track_count + " track CD was already ripped at " + (new Date(1000 * Number(m[1])).toLocaleString());
  
                      } else if ((m=s.match(/unplugged_drive/))) {
                          $(".cd_status").html("Error");
                          s = "This " + data.data.state.cd.track_count + " CD ripped successfully, but failed to copy to storage because it was unplugged. Please rip again and do not unplug any storage during the rip.";
  
                      } else if ((m=s.match(/ripper_exit_code (.*)/))) {
                          $(".cd_status").html("Error");
                          s = "Track " + data.data.state.cd.track + " failed to extract.";
  
                      } else if ((m=s.match(/all_full/))) {
                          $(".cd_status").html("Not Ready");
                          s = "Can not rip because all attached storage drives are full.";
  
                      } else if ((m=s.match(/all_ro/))) {
                          $(".cd_status").html("Not Ready");
                          s = "Can not rip because all attached storage drives are read-only. Please make sure they are writable.";
  
                      } else if ((m=s.match(/no_drives/))) {
                          $(".cd_status").html("Not Ready");
                          s = "Can not rip because there are no attached storage drives. Please install internal storage or connect a USB drive.";
  
                      } else if ((m=s.match(/move_error (.*)/))) {
                          $(".cd_status").html("Error");
                          s = "This " + data.data.state.cd.track_count + " CD ripped successfully, but failed to copy to storage. Is your storage plugged in, writeable, and not full?";
  
  		    } else {
                          $(".cd_status").html("Error");
                          if (data.data.state.cd.track_count) {
                              s = "Failure processing this " + data.data.state.cd.track_count + " track CD.<br>" + s;
                          } else {
                              s = "Failure processing CD.<br>" + s;
                          }
                      }
  
                      $(".cd_description").html(s);
  
                  } else {
                      $(".cd_status").addClass("text-danger").removeClass("text-success");
                      $(".cd_description").html("Unknown");
                      $(".cd_description").html("Unknown status: " + data.data.state.cd.status);
                  }
              } else {
                  $(".cd_status").addClass("text-success").removeClass("text-danger");
                  $(".cd_status").html("Not Available");
                  $(".action_cdeject").remove();
              }
  
              if (data.data.state.roon_running && data.data.state.has_ffmpeg) {
                  $(".software_status").addClass("text-success").removeClass("text-danger");
                  str = "";
                  if (data.data.state.roon_version)
                      str += "<div>Version " + data.data.state.roon_version + "</div>";
  
                  if (data.data.state.roon_uptime)
                      str += "<div>Running " + roonuptime + ".</div>";
  
                  $(".software_status").html("OK");
                  $(".software_description").html(str);
                  $(".case_softwarenotrunning").remove();
                  $(".case_missingcodecs").remove();
  
              } else if (!data.data.state.has_ffmpeg) {
                  $(".software_status").addClass("text-danger").removeClass("text-success");
                  $(".software_status").html("Missing Codecs");
                  $(".case_softwarerunning").remove();
                  $(".case_softwarenotrunning").remove();
  
              } else {
                  $(".software_status").addClass("text-danger").removeClass("text-success");
                  $(".software_status").html("Not Running");
                  $(".case_softwarerunning").remove();
                  $(".case_missingcodecs").remove();
              }
  
              if (data.data.state.has_vendor) {
                  if (!data.data.state.vendor_can_stop) {
                      $(".case_vendoraction").remove();
                  }
                  if (data.data.state.vendor_running) {
                      $(".vendorsoftware_status").addClass("text-success").removeClass("text-danger");
                      str = "";
                      if (data.data.state.vendor_version)
                          str += "<div>Version " + data.data.state.vendor_version + ".</div>";
  
                      if (data.data.state.vendor_uptime)
                          str += "<div>Running " + vendoruptime + ".</div>";
  
                      $(".vendorsoftware_status").html("OK");
                      $(".vendorsoftware_description").html(str);
                      $(".case_vendorsoftwarenotrunning").remove();
  
                  } else {
                      $(".vendorsoftware_status").addClass("text-danger").removeClass("text-success");
                      $(".vendorsoftware_status").html("Not Running");
                      $(".case_vendorsoftwarerunning").remove();
                  }
              } else {
                  $(".vendorsoftwarearea").hide();
              }
  
              if (data.data.state.tailscale && data.data.state.tailscale.enabled) {
                  $(".tailscale_status").addClass("text-success");
                  $(".tailscale_status").html("OK");
                  $(".tailscale_username").text(data.data.state.tailscale.username);
                  $(".tailscale_username").show();
                  $(".action_show_tailscale").hide();
                  $(".action_logout_tailscale").show();
              } else {
                  $(".tailscale_status").removeClass("text-success");
                  $(".tailscale_username").text("");
                  $(".tailscale_username").hide();
                  $(".tailscale_status").html("Not signed in");
                  $(".action_show_tailscale").show();
                  $(".action_logout_tailscale").hide();
              }
  
              for (i in data.data.interfaces) {
                  (function() {
                      var iface = data.data.interfaces[i];
  
                      var page = $("<div class='tab-pane' id='interface_page_" + iface['interface'] + "'></div>");
                      var tab  = $("<li id='interface_tab_" + iface['interface'] + "'><a href='#interface_page_" + iface['interface'] + "'>" + iface.name + "</a></li>");
                      $("#interfaces_tabs").append(tab);
                      $("#interfaces_pages").append(page);
  
                      var pagebody = $('.interface_template').clone().removeClass("interface_template").show();
  
                      if (iface['interface'] == 'eth0') {
                          pagebody.find(".enableinterface").hide();
                      }
  
                      var showall = function() {
                          pagebody.find(".allsettings").show();
                      };
                      var hideall = function() {
                          pagebody.find(".allsettings").hide();
                      };
                      var showdhcp = function() {
                          pagebody.find(".config_ip").val(iface.state.ip);
                          pagebody.find(".config_netmask").val(iface.state.netmask);
                          pagebody.find(".config_gateway").val(iface.state.gateway);
                          pagebody.find(".config_dns").val(iface.state.dns);
                          pagebody.find(".config_ip").attr('readonly', 'readonly');
                          pagebody.find(".config_netmask").attr('readonly', 'readonly');
                          pagebody.find(".config_gateway").attr('readonly', 'readonly');
                          pagebody.find(".config_dns").attr('readonly', 'readonly');
                      };
                      var showstatic = function() {
                          pagebody.find(".config_ip").val(iface.config.static_ip);
                          pagebody.find(".config_netmask").val(iface.config.static_netmask);
                          pagebody.find(".config_gateway").val(iface.config.static_gateway);
                          pagebody.find(".config_dns").val(iface.config.static_dns);
                          pagebody.find(".config_ip").removeAttr('readonly');
                          pagebody.find(".config_netmask").removeAttr('readonly');
                          pagebody.find(".config_gateway").removeAttr('readonly');
                          pagebody.find(".config_dns").removeAttr('readonly');
                      };
  
                      pagebody.find('.config_dhcp'    ).on("change", function() { if ($(this).prop("checked")) { showdhcp(); } });
                      pagebody.find('.config_staticip').on("change", function() { if ($(this).prop("checked")) { showstatic(); } });
                      pagebody.find('.config_enabled' ).on("change", function() { if ($(this).prop("checked")) { showall(); } });
                      pagebody.find('.config_disabled').on("change", function() { if ($(this).prop("checked")) { hideall(); } });
  
                      pagebody.find(".config_enabled" ).attr("name", "enablement" + iface["interface"]);
                      pagebody.find(".config_disabled").attr("name", "enablement" + iface["interface"]);
  
                      if (iface.config.enabled) {
                          pagebody.find(".config_enabled").closest(".btn").button('toggle');
                          showall();
                      } else {
                          pagebody.find(".config_disabled").closest(".btn").button('toggle');
                          hideall();
                      }
                      if (iface.config.use_dhcp) {
                          pagebody.find(".config_dhcp").closest(".btn").button('toggle');
                          showdhcp();
                      } else {
                          pagebody.find(".config_staticip").closest(".btn").button('toggle');
                          showstatic();
                      }
  
                      if (iface.config.wifi_ssid === undefined) {
                          pagebody.find(".config_wifi"      ).closest(".form-group").hide();
                          pagebody.find(".wifisettings"     ).hide();
                      } else {
                          pagebody.find(".config_ssid"      ).val(iface.config.wifi_ssid);
                          pagebody.find(".config_security .title").text(iface.config.wifi_type ? iface.config.wifi_type : "None");
                          pagebody.find(".config_passphrase").val(iface.config.wifi_key);
                          pagebody.find(".wifi_scan_button").on("click", function(event) {
                              event.preventDefault();
                              wifiscan(iface['interface'], pagebody);
                          });
                          pagebody.find(".wifi_security_wpa2").on("click", function(event) { event.preventDefault(); pagebody.find(".config_security .title").text("WPA2"); });
                          pagebody.find(".wifi_security_wpa" ).on("click", function(event) { event.preventDefault(); pagebody.find(".config_security .title").text("WPA" ); });
                          pagebody.find(".wifi_security_wep" ).on("click", function(event) { event.preventDefault(); pagebody.find(".config_security .title").text("WEP" ); });
                          pagebody.find(".wifi_security_none").on("click", function(event) { event.preventDefault(); pagebody.find(".config_security .title").text("None"); });
                      }
  
                      if (iface.config.wifi_ssid === undefined) {
                          pagebody.find(".current_ssid_area").hide();
                      } else {
                          pagebody.find(".current_ssid").val(iface.state.wifi_ssid);
                      }
  
                      page.append(pagebody);
  
                      tab.find("a").click(function (e) { e.preventDefault(); $(this).tab('show'); });
                      if (i == 0) tab.find("a").tab('show');
                  })();
              }
  
              $("#allbodyloading").hide();
              $(".main_area").show();
  
          } catch (e) {
              console.log(data);
              console.log(e);
              $("#allbodyloading").hide();
              $("#main_error_text").text("Failed to load device state (unexpected error). Please refresh.");
              $("#main_error").show();
          }
  
      } else {
          console.log(data);
          $("#allbodyloading").hide();
          $("#main_error_text").text("Failed to load device state (" + data.status + "). Please refresh.");
          $("#main_error").show();
      }
  })
  .fail(function(data) {
      console.log(data);
      $("#allbodyloading").hide();
      $("#main_error_text").text("Failed to load device state (status: " + data.status + "). Please refresh.");
      $("#main_error").show();
  });
  
  
  var networks = [];
  
  function wifiscan(ifi, root) {
      $("#wifi_scan_modal_title").text("Scanning for wireless networks...");
      $.ajax({
          type: "POST",
          url: HttpRoot + "1/wifi/scan",
          dataType: "json",
          data: { "interface": ifi }
      });
      var n = 20;
      var go = function() {
          $.ajax({
              type: "POST",
              url: HttpRoot + "1/wifi/scanresults",
              dataType: "json",
              data: { "interface": ifi }
          }).done(function (data) {
              $("#wifi_scan_modal .modal-body").html("");
              networks = data.networks;
              if (data.networks) {
                  for (x in data.networks) {
                      (function() {
                          var n = data.networks[x];
  
                          var row = $("<div class='scan_row clearfix'><div class='scan_ssid'></div><button class='btn btn-primary pull-right'>Connect</button><span class='scan_ssid_lock glyphicon glyphicon-lock pull-right'></span></div>");
                          row.find(".scan_ssid").text(n.SSID);
                          if (n.encryption == "None") row.find(".scan_ssid_lock").remove();
                          row.find("button").on("click", function() {
                              root.find(".config_ssid").val(n.SSID);
                              root.find(".config_security .title").text(n.encryption);
                              if (n.encryption != "None") {
                                  $(".input_ssid").val(n.SSID);
                                  $(".input_passphrase").val("");
                                  $("#wifi_key_modal").modal('show');
                                  $("#wifi_key_modal form").on('submit', function(event) {
                                      event.preventDefault();
                                      root.find(".config_passphrase").val($(".input_passphrase").val());
                                      $("#wifi_key_modal").modal('hide');
                                      $("#wifi_scan_modal").modal('hide');
                                  });
                              } else {
                                  $("#wifi_scan_modal").modal('hide');
                              }
                          });
                          $("#wifi_scan_modal .modal-body").append(row);
                      })();
                  }
              }
          });
          setTimeout(function() {
              n--;
              if (n > 0) {
                  go();
              } else {
                  if (networks.length == 0) {
                      $("#wifi_scan_modal #wifi_scan_modal_title").text("No Wireless Networks Found");
                  } else if (networks.length == 1) {
                      $("#wifi_scan_modal #wifi_scan_modal_title").text("1 Wireless Network Found");
                  } else {
                      $("#wifi_scan_modal #wifi_scan_modal_title").text(networks.length.toString() + " Wireless Networks Found");
                  }
              }
          }, 1000);
      }
      go();
  }
  
  function action_delete() {
      $("#confirm_modal .title").text("Reset?");
      $("#confirm_modal .text").html("<p>Are you sure you want to reset all settings and databases? This action is destructive and can not be undone.</p><p>This will also destroy your network settings, so make sure you have your device on the network via an ethernet cable.</p>");
      $("#confirm_modal .ok").text("Yes");
      $("#confirm_modal .cancel").text("No");
      $("#confirm_modal .ok").unbind("click");
      $("#confirm_modal .ok").on("click", function(event) {
          event.preventDefault();
          $("#confirm_modal").modal('hide');
  
          working_modal({ title: "Resetting settings and databases", text: "Resetting settings and databases. This can take a few minutes, please wait until it is complete." });
  
          $.ajax({ type: "POST", url: HttpRoot + "1/delete", dataType: "json", data: { } })
          .done(function(data) {
              if (data.status == "Success") {
                  $.ajax({ type: "POST", url: HttpRoot + "1/getstate", dataType: "json", data: { }, timeout: 1000 })
                  .done(function(data) {
                      working_modal_hide();
                      message_modal({ title: "Success", text: "Settings and databases have been reset successfully." });
                  })
                  .fail(function(data) {
                      working_modal_hide();
                      message_modal({ title: "Success", text: "Settings and databases have been reset successfully. However, it seems the IP Address of your device has changed, so you will need to return to the Roon application to determine the new IP of this device." });
                  });
              } else {
                  working_modal_hide();
                  message_modal({ title: "Error", text: "Settings and databases could not be reset. Please try again, or contact support.\n" + JSON.stringify(data) });
              }
          })
          .fail(function(data) {
              working_modal_hide();
              message_modal({ title: "Error", text: "Settings and databases could not be reset. Please try again, or contact support." });
          });
      });
      $("#confirm_modal").modal("show");
  }
  
  function action_show_tailscale() {
      $("#tailscale_modal").modal("show");
  }
  
  function action_login_tailscale() {
      $.ajax({ type: "POST", url: HttpRoot + "1/tailscale/start", dataType: "json", data: { } })
          .done(function(data) {
              if (data.loginUrl)
                  window.open(data.loginUrl, "_blank");
              else
                  message_modal({ title: "Error", text: "Tailscale could not be started. Try again or try to reboot." });
          })
          .fail(function(data) {
              message_modal({ title: "Error", text: "Tailscale could not be started. Try again or try to reboot." });
          });
  }
  
  
  
  function action_logout_tailscale() {
      $.ajax({ type: "POST", url: HttpRoot + "1/tailscale/stop", dataType: "json", data: { } })
          .done(function(data) {
              document.location.reload(true);
          })
          .fail(function(data) {
              message_modal({ title: "Error", text: "Tailscale could not be signed out from. Try again or try to reboot. You can also disable tailscale for this host from your Tailscale console." });
          });
  }
  
  function action_format() {
      $("#confirm_modal .title").text("Format Internal Storage?");
      $("#confirm_modal .text").html("<p>Are you sure you want to delete all the content on your internal storage disk? This action is destructive and can not be undone.</p><p>This will not hurt your Roon Database or settings, but it will delete everything on the music storage disk inside your device.</p>");
      $("#confirm_modal .ok").text("Yes");
      $("#confirm_modal .cancel").text("No");
      $("#confirm_modal .ok").unbind("click");
      $("#confirm_modal .ok").on("click", function(event) {
          event.preventDefault();
          $("#confirm_modal").modal('hide');
  
          working_modal({ title: "Formatting internal storage disk", text: "Formatting internal storage disk. This can take a few minutes, please wait until it is complete." });
  
          $.ajax({ type: "POST", url: HttpRoot + "1/formatinternalstorage", dataType: "json", data: { } })
          .done(function(data) {
              if (data.status == "Success") {
                  $.ajax({ type: "POST", url: HttpRoot + "1/getstate", dataType: "json", data: { }, timeout: 1000 })
                  .done(function(data) {
                      working_modal_hide();
                      message_modal({ title: "Success", text: "Internal storage disk formatted successfully." });
                  })
                  .fail(function(data) {
                      working_modal_hide();
                      message_modal({ title: "Success", text: "Internal storage disk formatted successfully. However, it seems the IP Address of your device has changed, so you will need to return to the Roon application to determine the new IP of this device." });
                  });
              } else {
                  working_modal_hide();
                  message_modal({ title: "Error", text: "Internal storage disk could not be formatted. Please try again, or contact support.\n" + JSON.stringify(data) });
              }
          })
          .fail(function(data) {
              working_modal_hide();
              message_modal({ title: "Error", text: "Internal storage disk could not be formatted. Please try again, or contact support." });
          });
      });
      $("#confirm_modal").modal("show");
  }
  
  function action_cdeject() {
      $.ajax({ type: "POST", url: HttpRoot + "1/eject", dataType: "json", data: { } })
      .done(function(data) {
      })
      .fail(function(data) {
          message_modal({ title: "Error", text: "Unable to eject CD. Please try again, or contact support." });
      });
  }
  
  function action_reinstall() {
      $("#confirm_modal .title").text("Update/Reinstall?");
      $("#confirm_modal .text").html("<p>Are you sure you want to update/reinstall the latest software?</p><p>This requires an internet connection and could take a few minutes to download. This action is destructive and can not be undone.</p><p>This will not modify any of your settings or databases.</p>");
      $("#confirm_modal .ok").text("Yes");
      $("#confirm_modal .cancel").text("No");
      $("#confirm_modal .ok").unbind("click");
      $("#confirm_modal .ok").on("click", function(event) {
          event.preventDefault();
          $("#confirm_modal").modal('hide');
  
          working_modal({ title: "Updating and Reinstalling", text: "Reinstalling latest software. This can take some time to download and install. Please wait until it is complete." });
  
          var retries = 240; // 240 * 5 seconds == 20 minutes
          var check = function() {
              if (--retries == 0) {
                  working_modal_hide();
                  message_modal({ title: "Error", text: "Something went wrong with the installation. Please check your internet connection and try again." });
              } else {
                  setTimeout(function() {
                      $.ajax({ type: "POST", url: HttpRoot + "1/getstate", dataType: "json", data: { }, timeout: 5000 })
                      .done(function(data) {
                          if (data.status == "Success" && data.data.state.roon_running) {
                              working_modal_hide();
                              message_modal({ title: "Success", text: "Successfully reinstalled system." });
                          } else {
                              check();
                          }
                      })
                      .fail(function(data) {
                          check();
                      });
                  }, 5000);
              }
          };
  
          $.ajax({ type: "POST", url: HttpRoot + "1/reinstall", dataType: "json", data: { }, timeout: 900000 })
          .done(function(data) {
              if (data.status != "Success") {
                  working_modal_hide();
                  if (data.exitcode >= 10 && data.exitcode < 20) {
                      message_modal({ title: "Error", text: "There was an error downloading Roon. Please check your internet connection.\n" + JSON.stringify(data) })
                  } else if (data.exitcode >= 20 && data.exitcode < 30) {
                      message_modal({ title: "Error", text: "There was an error downloading " + gd.data.device_vendor + " Software. Please check your internet connection.\n" + JSON.stringify(data) })
                  } else if (data.exitcode >= 30 && data.exitcode < 40) {
                      message_modal({ title: "Error", text: "There was an error downloading the operating system. Please check your internet connection.\n" + JSON.stringify(data) })
                  } else if (data.exitcode >= 40 && data.exitcode < 50) {
                      message_modal({ title: "Error", text: "There was an error installing the software. Please take a screenshot and contact support.\n" + JSON.stringify(data) })
                  } else if (data.exitcode >= 50 && data.exitcode < 60) {
                      message_modal({ title: "Error", text: "There was an error reinstalling your operating system. Please take a screenshot and contact support.\n" + JSON.stringify(data) })
                  } else if (data.exitcode >= 60 && data.exitcode < 69) {
  	           message_modal({ title: "Error", html: "There was an error reinstalling your operating system because your \"Reinstall\" folder is misconfigured. Please visit <a target='_blank' href='https://roon.link/RoonOS/reinstall-directory-misconfigured'>this help center article</a> for more information." })
                  }
              } else {
                  check();
              }
          })
          .fail(function(data) {
              check();
          });
      });
      $("#confirm_modal").modal("show");
  }
  function action_stopsoftware(softwaretype, runningvarname, softwarename) {
      $("#confirm_modal .title").text("Stop " + softwarename + "?");
      $("#confirm_modal .text").text("Are you sure you want to stop " + softwarename + "? All connected remotes will be temporarily disconnected.");
      $("#confirm_modal .ok").text("Yes");
      $("#confirm_modal .cancel").text("No");
      $("#confirm_modal .ok").unbind("click");
      $("#confirm_modal .ok").on("click", function(event) {
          event.preventDefault();
          $("#confirm_modal").modal('hide');
  
          var retries = 15; // 15 * 1 second
          var check = function() {
              if (--retries == 0) {
                  working_modal_hide();
                  message_modal({ title: "Stop error", text: softwarename + " could not be successfully stopped. Please try rebooting, or contact support." });
              } else {
                  setTimeout(function() {
                      $.ajax({ type: "POST", url: HttpRoot + "1/getstate", dataType: "json", data: { }, timeout: 1000 })
                      .done(function(data) {
                          if (data.status == "Success" && !data.data.state[runningvarname]) {
                              working_modal_hide();
                              message_modal({ title: "Stopped", text: softwarename + " was successfully stopped." });
                          } else {
                              check();
                          }
                      })
                      .fail(function(data) {
                          check();
                      });
                  }, 1000);
              }
          };
  
          working_modal({ title: "Stopping", text: "Stopped " + softwarename + ". Waiting for it to shut down..."});
          $.ajax({ type: "POST", url: HttpRoot + "1/stop" + softwaretype + "software", dataType: "json", data: { } })
          .done(function(data) {
              check();
          })
          .fail(function(data) {
              working_modal_hide();
              message_modal({ title: "Stop error", text: softwarename + " could not be successfully stopped. Please check your network connection." });
          });
      });
      $("#confirm_modal").modal("show");
  }
  function action_restartsoftware(softwaretype, runningvarname, softwarename) {
      $("#confirm_modal .title").text("Restart " + softwarename + "?");
      $("#confirm_modal .text").text("Are you sure you want to restart " + softwarename + "? All connected remotes will be temporarily disconnected.");
      $("#confirm_modal .ok").text("Yes");
      $("#confirm_modal .cancel").text("No");
      $("#confirm_modal .ok").unbind("click");
      $("#confirm_modal .ok").on("click", function(event) {
          event.preventDefault();
          $("#confirm_modal").modal('hide');
  
          var retries = 15; // 15 * 1 second
          var check = function() {
              if (--retries == 0) {
                  working_modal_hide();
                  message_modal({ title: "Restart Error", text: softwarename + " could not be successfully restarted. Please try rebooting, or contact support." });
              } else {
                  setTimeout(function() {
                      $.ajax({ type: "POST", url: HttpRoot + "1/getstate", dataType: "json", data: { }, timeout: 1000 })
                      .done(function(data) {
                          if (data.status == "Success" && data.data.state[runningvarname]) {
                              working_modal_hide();
                              message_modal({ title: "Restarted", text: softwarename + " was successfully restarted." });
                          } else {
                              check();
                          }
                      })
                      .fail(function(data) {
                          check();
                      });
                  }, 1000);
              }
          };
  
          working_modal({ title: "Restarting software", text: "Restarted " + softwarename + ". Waiting for it to become available again..."});
          $.ajax({ type: "POST", url: HttpRoot + "1/restart" + softwaretype + "software", dataType: "json", data: { } })
          .done(function(data) {
              check();
          })
          .fail(function(data) {
              working_modal_hide();
              message_modal({ title: "Restart Error", text: softwarename + " could not be successfully restarted. Please check your network connection." });
          });
      });
      $("#confirm_modal").modal("show");
  }
  function action_reboot() {
      $("#confirm_modal .title").text("Reboot?");
      $("#confirm_modal .text").text("Are you sure you want to reboot? All connected remotes will be temporarily disconnected.");
      $("#confirm_modal .ok").text("Yes");
      $("#confirm_modal .cancel").text("No");
      $("#confirm_modal .ok").unbind("click");
      $("#confirm_modal .ok").on("click", function(event) {
          event.preventDefault();
          $("#confirm_modal").modal('hide');
  
          var retries = 30; // 30 * 1 second
          var check = function() {
              if (--retries == 0) {
                  working_modal_hide();
                  message_modal({ title: "Error", text: "Device has not rebooted. Please try manually powering off, or contact support." });
              } else {
                  setTimeout(function() {
                      $.ajax({ type: "POST", url: HttpRoot + "1/getstate", dataType: "json", data: { }, timeout: 1000 })
                      .done(function(data) {
                          if (data.status == "Success") {
                    
services.name: http://162.204.10.214/favicon.ico
services.body_hash_sha1: sha1:6ee5edc5356daeb2290a48823cdaa428201146e4
services.supported_versions: HTTP/1.1 HTTP/2
services.protocol: NETBIOS
services.transport_protocol: UDP
services.scan_time: 2025-07-27T11:41:19.840911
services.protocol: HTTP
services.transport_protocol: TCP
services.scan_time: 2025-07-28T07:39:03.964354
services.banner: HTTP/1.1 404 Not Found
  Content-Length: 0
  
services.path: /
services.endpoint_type: HTTP
services.scan_time: 2025-07-28T07:39:03.964354
services.uri: http://162.204.10.214:9330/
services.protocol: HTTP/1.1
services.status_reason: Not Found
services.key: Content-Length
services.headers: 0
services.supported_versions: HTTP/1.1
services.protocol: HTTP
services.transport_protocol: TCP
services.scan_time: 2025-07-28T04:58:32.759188
services.banner: HTTP/1.1 404 Not Found
  Content-Length: 0
  
services.version_selected: TLSv1_2
services.cipher_selected: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
services.ja4s: t120300_c030_bec8bdbaef8a
services.version: TLSv1_2
services.ja4s: t120300_c030_bec8bdbaef8a
services.names: localhost
services.issuer_dn: C=US, ST=NY, L=NYC, O=Roon Labs LLC, CN=RoonCA, emailAddress=support@roonlabs.com
services.common_name: RoonCA
services.country: US
services.locality: NYC
services.province: NY
services.organization: Roon Labs LLC
services.email_address: support@roonlabs.com
services.subject_dn: C=US, ST=NY, L=NYC, O=Roon Labs LLC, CN=RoonBroker, emailAddress=support@roonlabs.com
services.common_name: RoonBroker
services.country: US
services.locality: NYC
services.province: NY
services.organization: Roon Labs LLC
services.email_address: support@roonlabs.com
services.scan_time: 2025-07-20T02:25:01.180321
services.path: /
services.endpoint_type: HTTP
services.scan_time: 2025-07-28T04:58:32.759188
services.uri: https://162.204.10.214:55002/
services.protocol: HTTP/1.1
services.status_reason: Not Found
services.key: Content-Length
services.headers: 0
services.supported_versions: HTTP/1.1
[binary data, 24 values, 855 bytes]