1*cf78ab8cSAndroid Build Coastguard Workerimport {css, html, LitElement} from 'lit'; 2*cf78ab8cSAndroid Build Coastguard Workerimport {customElement, property} from 'lit/decorators.js'; 3*cf78ab8cSAndroid Build Coastguard Worker 4*cf78ab8cSAndroid Build Coastguard Workerimport {Device, Notifiable, SimulationInfo, simulationState,} from './device-observer.js'; 5*cf78ab8cSAndroid Build Coastguard Workerimport {Capture} from './netsim/model.js'; 6*cf78ab8cSAndroid Build Coastguard Worker 7*cf78ab8cSAndroid Build Coastguard Worker@customElement('ns-packet-info') 8*cf78ab8cSAndroid Build Coastguard Workerexport class PacketInformation extends LitElement implements Notifiable { 9*cf78ab8cSAndroid Build Coastguard Worker /** 10*cf78ab8cSAndroid Build Coastguard Worker * List of captures currently on the netsim. 11*cf78ab8cSAndroid Build Coastguard Worker */ 12*cf78ab8cSAndroid Build Coastguard Worker @property() captureData: Capture[] = []; 13*cf78ab8cSAndroid Build Coastguard Worker 14*cf78ab8cSAndroid Build Coastguard Worker /** 15*cf78ab8cSAndroid Build Coastguard Worker * List of devices currently on the netsim. 16*cf78ab8cSAndroid Build Coastguard Worker */ 17*cf78ab8cSAndroid Build Coastguard Worker @property() deviceData: Device[] = []; 18*cf78ab8cSAndroid Build Coastguard Worker 19*cf78ab8cSAndroid Build Coastguard Worker static styles = css` 20*cf78ab8cSAndroid Build Coastguard Worker :host { 21*cf78ab8cSAndroid Build Coastguard Worker display: flex; 22*cf78ab8cSAndroid Build Coastguard Worker justify-content: center; 23*cf78ab8cSAndroid Build Coastguard Worker align-items: flex-start; 24*cf78ab8cSAndroid Build Coastguard Worker height: 100vh; 25*cf78ab8cSAndroid Build Coastguard Worker } 26*cf78ab8cSAndroid Build Coastguard Worker 27*cf78ab8cSAndroid Build Coastguard Worker .panel { 28*cf78ab8cSAndroid Build Coastguard Worker cursor: pointer; 29*cf78ab8cSAndroid Build Coastguard Worker display: grid; 30*cf78ab8cSAndroid Build Coastguard Worker place-content: center; 31*cf78ab8cSAndroid Build Coastguard Worker color: black; 32*cf78ab8cSAndroid Build Coastguard Worker font-size: 25px; 33*cf78ab8cSAndroid Build Coastguard Worker font-family: 'Lato', sans-serif; 34*cf78ab8cSAndroid Build Coastguard Worker border: 5px solid black; 35*cf78ab8cSAndroid Build Coastguard Worker border-radius: 12px; 36*cf78ab8cSAndroid Build Coastguard Worker margin: 10px; 37*cf78ab8cSAndroid Build Coastguard Worker padding: 10px; 38*cf78ab8cSAndroid Build Coastguard Worker background-color: #ffffff; 39*cf78ab8cSAndroid Build Coastguard Worker max-width: max-content; 40*cf78ab8cSAndroid Build Coastguard Worker float: left; 41*cf78ab8cSAndroid Build Coastguard Worker } 42*cf78ab8cSAndroid Build Coastguard Worker 43*cf78ab8cSAndroid Build Coastguard Worker .title { 44*cf78ab8cSAndroid Build Coastguard Worker font-weight: bold; 45*cf78ab8cSAndroid Build Coastguard Worker text-transform: uppercase; 46*cf78ab8cSAndroid Build Coastguard Worker text-align: center; 47*cf78ab8cSAndroid Build Coastguard Worker margin-bottom: 10px; 48*cf78ab8cSAndroid Build Coastguard Worker } 49*cf78ab8cSAndroid Build Coastguard Worker 50*cf78ab8cSAndroid Build Coastguard Worker .label { 51*cf78ab8cSAndroid Build Coastguard Worker text-align: left; 52*cf78ab8cSAndroid Build Coastguard Worker } 53*cf78ab8cSAndroid Build Coastguard Worker 54*cf78ab8cSAndroid Build Coastguard Worker .styled-table { 55*cf78ab8cSAndroid Build Coastguard Worker border-collapse: collapse; 56*cf78ab8cSAndroid Build Coastguard Worker margin: 25px 0; 57*cf78ab8cSAndroid Build Coastguard Worker font-size: 20px; 58*cf78ab8cSAndroid Build Coastguard Worker font-family: sans-serif; 59*cf78ab8cSAndroid Build Coastguard Worker width: 100%; 60*cf78ab8cSAndroid Build Coastguard Worker box-shadow: 0 0 20px rgba(0, 0, 0, 0.15); 61*cf78ab8cSAndroid Build Coastguard Worker } 62*cf78ab8cSAndroid Build Coastguard Worker 63*cf78ab8cSAndroid Build Coastguard Worker .styled-table thead tr { 64*cf78ab8cSAndroid Build Coastguard Worker background-color: #009879; 65*cf78ab8cSAndroid Build Coastguard Worker color: #ffffff; 66*cf78ab8cSAndroid Build Coastguard Worker text-align: left; 67*cf78ab8cSAndroid Build Coastguard Worker } 68*cf78ab8cSAndroid Build Coastguard Worker 69*cf78ab8cSAndroid Build Coastguard Worker .styled-table th, 70*cf78ab8cSAndroid Build Coastguard Worker .styled-table td { 71*cf78ab8cSAndroid Build Coastguard Worker padding: 12px 15px; 72*cf78ab8cSAndroid Build Coastguard Worker text-align: left; 73*cf78ab8cSAndroid Build Coastguard Worker } 74*cf78ab8cSAndroid Build Coastguard Worker 75*cf78ab8cSAndroid Build Coastguard Worker .styled-table tbody tr { 76*cf78ab8cSAndroid Build Coastguard Worker border-bottom: 1px solid #dddddd; 77*cf78ab8cSAndroid Build Coastguard Worker } 78*cf78ab8cSAndroid Build Coastguard Worker 79*cf78ab8cSAndroid Build Coastguard Worker .styled-table tbody tr:nth-of-type(even) { 80*cf78ab8cSAndroid Build Coastguard Worker background-color: #cac0c0; 81*cf78ab8cSAndroid Build Coastguard Worker } 82*cf78ab8cSAndroid Build Coastguard Worker 83*cf78ab8cSAndroid Build Coastguard Worker input[type='button'] { 84*cf78ab8cSAndroid Build Coastguard Worker height: 2rem; 85*cf78ab8cSAndroid Build Coastguard Worker font-size: inherit; 86*cf78ab8cSAndroid Build Coastguard Worker } 87*cf78ab8cSAndroid Build Coastguard Worker 88*cf78ab8cSAndroid Build Coastguard Worker input[type='checkbox'].switch_1 { 89*cf78ab8cSAndroid Build Coastguard Worker font-size: 30px; 90*cf78ab8cSAndroid Build Coastguard Worker -webkit-appearance: none; 91*cf78ab8cSAndroid Build Coastguard Worker -moz-appearance: none; 92*cf78ab8cSAndroid Build Coastguard Worker appearance: none; 93*cf78ab8cSAndroid Build Coastguard Worker width: 3.5em; 94*cf78ab8cSAndroid Build Coastguard Worker height: 1.5em; 95*cf78ab8cSAndroid Build Coastguard Worker background: #ddd; 96*cf78ab8cSAndroid Build Coastguard Worker border-radius: 3em; 97*cf78ab8cSAndroid Build Coastguard Worker position: relative; 98*cf78ab8cSAndroid Build Coastguard Worker cursor: pointer; 99*cf78ab8cSAndroid Build Coastguard Worker outline: none; 100*cf78ab8cSAndroid Build Coastguard Worker -webkit-transition: all 0.2s ease-in-out; 101*cf78ab8cSAndroid Build Coastguard Worker transition: all 0.2s ease-in-out; 102*cf78ab8cSAndroid Build Coastguard Worker } 103*cf78ab8cSAndroid Build Coastguard Worker 104*cf78ab8cSAndroid Build Coastguard Worker input[type='checkbox'].switch_1:checked { 105*cf78ab8cSAndroid Build Coastguard Worker background: #0ebeff; 106*cf78ab8cSAndroid Build Coastguard Worker } 107*cf78ab8cSAndroid Build Coastguard Worker 108*cf78ab8cSAndroid Build Coastguard Worker input[type='checkbox'].switch_1:after { 109*cf78ab8cSAndroid Build Coastguard Worker position: absolute; 110*cf78ab8cSAndroid Build Coastguard Worker content: ''; 111*cf78ab8cSAndroid Build Coastguard Worker width: 1.5em; 112*cf78ab8cSAndroid Build Coastguard Worker height: 1.5em; 113*cf78ab8cSAndroid Build Coastguard Worker border-radius: 50%; 114*cf78ab8cSAndroid Build Coastguard Worker background: #fff; 115*cf78ab8cSAndroid Build Coastguard Worker -webkit-box-shadow: 0 0 0.25em rgba(0, 0, 0, 0.3); 116*cf78ab8cSAndroid Build Coastguard Worker box-shadow: 0 0 0.25em rgba(0, 0, 0, 0.3); 117*cf78ab8cSAndroid Build Coastguard Worker -webkit-transform: scale(0.7); 118*cf78ab8cSAndroid Build Coastguard Worker transform: scale(0.7); 119*cf78ab8cSAndroid Build Coastguard Worker left: 0; 120*cf78ab8cSAndroid Build Coastguard Worker -webkit-transition: all 0.2s ease-in-out; 121*cf78ab8cSAndroid Build Coastguard Worker transition: all 0.2s ease-in-out; 122*cf78ab8cSAndroid Build Coastguard Worker } 123*cf78ab8cSAndroid Build Coastguard Worker 124*cf78ab8cSAndroid Build Coastguard Worker input[type='checkbox'].switch_1:checked:after { 125*cf78ab8cSAndroid Build Coastguard Worker left: calc(100% - 1.5em); 126*cf78ab8cSAndroid Build Coastguard Worker } 127*cf78ab8cSAndroid Build Coastguard Worker 128*cf78ab8cSAndroid Build Coastguard Worker button { 129*cf78ab8cSAndroid Build Coastguard Worker display: inline-block; 130*cf78ab8cSAndroid Build Coastguard Worker padding: 12px 24px; 131*cf78ab8cSAndroid Build Coastguard Worker background-color: #4CAF50; 132*cf78ab8cSAndroid Build Coastguard Worker color: #FFFFFF; 133*cf78ab8cSAndroid Build Coastguard Worker font-size: 18px; 134*cf78ab8cSAndroid Build Coastguard Worker font-weight: bold; 135*cf78ab8cSAndroid Build Coastguard Worker text-align: center; 136*cf78ab8cSAndroid Build Coastguard Worker text-decoration: none; 137*cf78ab8cSAndroid Build Coastguard Worker border: none; 138*cf78ab8cSAndroid Build Coastguard Worker cursor: pointer; 139*cf78ab8cSAndroid Build Coastguard Worker transition: background-color 0.3s ease; 140*cf78ab8cSAndroid Build Coastguard Worker } 141*cf78ab8cSAndroid Build Coastguard Worker 142*cf78ab8cSAndroid Build Coastguard Worker button:hover { 143*cf78ab8cSAndroid Build Coastguard Worker background-color: #45a049; 144*cf78ab8cSAndroid Build Coastguard Worker transition: 0.5s; 145*cf78ab8cSAndroid Build Coastguard Worker } 146*cf78ab8cSAndroid Build Coastguard Worker `; 147*cf78ab8cSAndroid Build Coastguard Worker 148*cf78ab8cSAndroid Build Coastguard Worker connectedCallback() { 149*cf78ab8cSAndroid Build Coastguard Worker super.connectedCallback(); // eslint-disable-line 150*cf78ab8cSAndroid Build Coastguard Worker simulationState.registerObserver(this); 151*cf78ab8cSAndroid Build Coastguard Worker } 152*cf78ab8cSAndroid Build Coastguard Worker 153*cf78ab8cSAndroid Build Coastguard Worker disconnectedCallback() { 154*cf78ab8cSAndroid Build Coastguard Worker simulationState.removeObserver(this); 155*cf78ab8cSAndroid Build Coastguard Worker super.disconnectedCallback(); // eslint-disable-line 156*cf78ab8cSAndroid Build Coastguard Worker } 157*cf78ab8cSAndroid Build Coastguard Worker 158*cf78ab8cSAndroid Build Coastguard Worker onNotify(data: SimulationInfo) { 159*cf78ab8cSAndroid Build Coastguard Worker this.captureData = data.captures; 160*cf78ab8cSAndroid Build Coastguard Worker this.deviceData = data.devices; 161*cf78ab8cSAndroid Build Coastguard Worker this.requestUpdate(); 162*cf78ab8cSAndroid Build Coastguard Worker } 163*cf78ab8cSAndroid Build Coastguard Worker 164*cf78ab8cSAndroid Build Coastguard Worker toggleCapture(capture: Capture) { 165*cf78ab8cSAndroid Build Coastguard Worker let id = capture.id.toString(); 166*cf78ab8cSAndroid Build Coastguard Worker let state = capture.state ? '0' : '1'; 167*cf78ab8cSAndroid Build Coastguard Worker simulationState.patchCapture(id, state); 168*cf78ab8cSAndroid Build Coastguard Worker } 169*cf78ab8cSAndroid Build Coastguard Worker 170*cf78ab8cSAndroid Build Coastguard Worker private handleGetChips(device: Device) { 171*cf78ab8cSAndroid Build Coastguard Worker let btTable = html``; 172*cf78ab8cSAndroid Build Coastguard Worker let uwbTable = html``; 173*cf78ab8cSAndroid Build Coastguard Worker let wifiTable = html``; 174*cf78ab8cSAndroid Build Coastguard Worker if ('chips' in device && device.chips) { 175*cf78ab8cSAndroid Build Coastguard Worker for (const chip of device.chips) { 176*cf78ab8cSAndroid Build Coastguard Worker if ('bt' in chip && chip.bt) { 177*cf78ab8cSAndroid Build Coastguard Worker let bleTable = html``; 178*cf78ab8cSAndroid Build Coastguard Worker let bclassicTable = html``; 179*cf78ab8cSAndroid Build Coastguard Worker if ('lowEnergy' in chip.bt && chip.bt.lowEnergy) { 180*cf78ab8cSAndroid Build Coastguard Worker bleTable = html` 181*cf78ab8cSAndroid Build Coastguard Worker <tr> 182*cf78ab8cSAndroid Build Coastguard Worker <td>BLE</td> 183*cf78ab8cSAndroid Build Coastguard Worker <td>${chip.bt.lowEnergy.rxCount ?? 0}</td> 184*cf78ab8cSAndroid Build Coastguard Worker <td>${chip.bt.lowEnergy.txCount ?? 0}</td> 185*cf78ab8cSAndroid Build Coastguard Worker </tr> 186*cf78ab8cSAndroid Build Coastguard Worker `; 187*cf78ab8cSAndroid Build Coastguard Worker } 188*cf78ab8cSAndroid Build Coastguard Worker if ('classic' in chip.bt && chip.bt.classic) { 189*cf78ab8cSAndroid Build Coastguard Worker bclassicTable = html` 190*cf78ab8cSAndroid Build Coastguard Worker <tr> 191*cf78ab8cSAndroid Build Coastguard Worker <td>Bluetooth Classic</td> 192*cf78ab8cSAndroid Build Coastguard Worker <td>${chip.bt.classic.rxCount ?? 0}</td> 193*cf78ab8cSAndroid Build Coastguard Worker <td>${chip.bt.classic.txCount ?? 0}</td> 194*cf78ab8cSAndroid Build Coastguard Worker </tr> 195*cf78ab8cSAndroid Build Coastguard Worker `; 196*cf78ab8cSAndroid Build Coastguard Worker } 197*cf78ab8cSAndroid Build Coastguard Worker btTable = html`${bleTable} ${bclassicTable}`; 198*cf78ab8cSAndroid Build Coastguard Worker } 199*cf78ab8cSAndroid Build Coastguard Worker if ('uwb' in chip && chip.uwb) { 200*cf78ab8cSAndroid Build Coastguard Worker uwbTable = html` 201*cf78ab8cSAndroid Build Coastguard Worker <tr> 202*cf78ab8cSAndroid Build Coastguard Worker <td>UWB</td> 203*cf78ab8cSAndroid Build Coastguard Worker <td>${chip.uwb.rxCount ?? 0}</td> 204*cf78ab8cSAndroid Build Coastguard Worker <td>${chip.uwb.txCount ?? 0}</td> 205*cf78ab8cSAndroid Build Coastguard Worker </tr> 206*cf78ab8cSAndroid Build Coastguard Worker `; 207*cf78ab8cSAndroid Build Coastguard Worker } 208*cf78ab8cSAndroid Build Coastguard Worker if ('wifi' in chip && chip.wifi) { 209*cf78ab8cSAndroid Build Coastguard Worker wifiTable = html` 210*cf78ab8cSAndroid Build Coastguard Worker <tr> 211*cf78ab8cSAndroid Build Coastguard Worker <td>WIFI</td> 212*cf78ab8cSAndroid Build Coastguard Worker <td>${chip.wifi.rxCount ?? 0}</td> 213*cf78ab8cSAndroid Build Coastguard Worker <td>${chip.wifi.txCount ?? 0}</td> 214*cf78ab8cSAndroid Build Coastguard Worker </tr> 215*cf78ab8cSAndroid Build Coastguard Worker `; 216*cf78ab8cSAndroid Build Coastguard Worker } 217*cf78ab8cSAndroid Build Coastguard Worker } 218*cf78ab8cSAndroid Build Coastguard Worker } 219*cf78ab8cSAndroid Build Coastguard Worker return html` 220*cf78ab8cSAndroid Build Coastguard Worker ${btTable} 221*cf78ab8cSAndroid Build Coastguard Worker ${uwbTable} 222*cf78ab8cSAndroid Build Coastguard Worker ${wifiTable} 223*cf78ab8cSAndroid Build Coastguard Worker `; 224*cf78ab8cSAndroid Build Coastguard Worker } 225*cf78ab8cSAndroid Build Coastguard Worker 226*cf78ab8cSAndroid Build Coastguard Worker private handleListCaptures(capture: Capture) { 227*cf78ab8cSAndroid Build Coastguard Worker return html` 228*cf78ab8cSAndroid Build Coastguard Worker <tr> 229*cf78ab8cSAndroid Build Coastguard Worker <td>${capture.deviceName}</td> 230*cf78ab8cSAndroid Build Coastguard Worker <td>${capture.chipKind}</td> 231*cf78ab8cSAndroid Build Coastguard Worker <td>${capture.size}</td> 232*cf78ab8cSAndroid Build Coastguard Worker <td>${capture.records}</td> 233*cf78ab8cSAndroid Build Coastguard Worker <td> 234*cf78ab8cSAndroid Build Coastguard Worker <input 235*cf78ab8cSAndroid Build Coastguard Worker type="checkbox" 236*cf78ab8cSAndroid Build Coastguard Worker class="switch_1" 237*cf78ab8cSAndroid Build Coastguard Worker .checked=${capture.state} 238*cf78ab8cSAndroid Build Coastguard Worker @click=${() => { 239*cf78ab8cSAndroid Build Coastguard Worker this.toggleCapture(capture); 240*cf78ab8cSAndroid Build Coastguard Worker }} 241*cf78ab8cSAndroid Build Coastguard Worker /> 242*cf78ab8cSAndroid Build Coastguard Worker </td> 243*cf78ab8cSAndroid Build Coastguard Worker <td> 244*cf78ab8cSAndroid Build Coastguard Worker <a 245*cf78ab8cSAndroid Build Coastguard Worker href="./v1/captures/${capture.id}" 246*cf78ab8cSAndroid Build Coastguard Worker target="_blank" 247*cf78ab8cSAndroid Build Coastguard Worker type="application/vnd.tcpdump.pcap" 248*cf78ab8cSAndroid Build Coastguard Worker ><button>Download</button></a 249*cf78ab8cSAndroid Build Coastguard Worker > 250*cf78ab8cSAndroid Build Coastguard Worker </td> 251*cf78ab8cSAndroid Build Coastguard Worker </tr> 252*cf78ab8cSAndroid Build Coastguard Worker ` 253*cf78ab8cSAndroid Build Coastguard Worker } 254*cf78ab8cSAndroid Build Coastguard Worker 255*cf78ab8cSAndroid Build Coastguard Worker render() { 256*cf78ab8cSAndroid Build Coastguard Worker return html` 257*cf78ab8cSAndroid Build Coastguard Worker <div class="panel"> 258*cf78ab8cSAndroid Build Coastguard Worker <div class="title">Packet Info</div> 259*cf78ab8cSAndroid Build Coastguard Worker ${this.deviceData.map(device => html` 260*cf78ab8cSAndroid Build Coastguard Worker <div class="label">${device.name}</div> 261*cf78ab8cSAndroid Build Coastguard Worker <table class="styled-table"> 262*cf78ab8cSAndroid Build Coastguard Worker <tr> 263*cf78ab8cSAndroid Build Coastguard Worker <th>Radio</th> 264*cf78ab8cSAndroid Build Coastguard Worker <th>RX Count</th> 265*cf78ab8cSAndroid Build Coastguard Worker <th>TX Count</th> 266*cf78ab8cSAndroid Build Coastguard Worker </tr> 267*cf78ab8cSAndroid Build Coastguard Worker ${this.handleGetChips(device)} 268*cf78ab8cSAndroid Build Coastguard Worker </table> 269*cf78ab8cSAndroid Build Coastguard Worker `)} 270*cf78ab8cSAndroid Build Coastguard Worker </div> 271*cf78ab8cSAndroid Build Coastguard Worker <div class="panel"> 272*cf78ab8cSAndroid Build Coastguard Worker <div class="title">Packet Capture</div> 273*cf78ab8cSAndroid Build Coastguard Worker <table class="styled-table"> 274*cf78ab8cSAndroid Build Coastguard Worker <tr> 275*cf78ab8cSAndroid Build Coastguard Worker <th>Device Name</th> 276*cf78ab8cSAndroid Build Coastguard Worker <th>Chip Kind</th> 277*cf78ab8cSAndroid Build Coastguard Worker <th>Bytes</th> 278*cf78ab8cSAndroid Build Coastguard Worker <th>Records</th> 279*cf78ab8cSAndroid Build Coastguard Worker <th>Capture State</th> 280*cf78ab8cSAndroid Build Coastguard Worker <th>Download Pcap</th> 281*cf78ab8cSAndroid Build Coastguard Worker </tr> 282*cf78ab8cSAndroid Build Coastguard Worker ${this.captureData.map(capture => this.handleListCaptures(capture))} 283*cf78ab8cSAndroid Build Coastguard Worker </table> 284*cf78ab8cSAndroid Build Coastguard Worker </div> 285*cf78ab8cSAndroid Build Coastguard Worker `; 286*cf78ab8cSAndroid Build Coastguard Worker } 287*cf78ab8cSAndroid Build Coastguard Worker} 288