Log Parser



  • Love the new log parser, would be nice to have a stand-alone one as well that can run locally on my computer?

    https://www.mysensors.org/build/parser


  • Admin

    You can actually copy/paste the embedded javascript to a standalone html page if you want. Here you go:

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"></link>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <div id="parser">
    <h4>Paste log from gateway or node here:</h4>
    <textarea class="form-control" @change="parse" rows="10" v-model="source"></textarea>
    <button @click="parse" class="btn btn-primary">Parse</button>
    <button @click="source=''" class="btn btn-default">Clear</button>
    <h4>Human readable output:</h4>
    <div class="table-responsive">
    <table class="table table-condensed">
    <tr>
    <th>Node Id</th>
    <th>Child Sensor</th>
    <th>Command Type</th>
    <th>Ack Req/Resp</th>
    <th>Type</th>
    <th>Payload</th>
    <th>Description</th>
    </tr>
    <tr v-for="r in parsed">
       <td v-for="c in r" v-html="c"></td>
    </tr>
    </table>
    </div>
    </div>
    
    <script>
    var types = {
    "presentation":[
    "S_DOOR",
    "S_MOTION",
    "S_SMOKE",
    "S_LIGHT",
    "S_DIMMER",
    "S_COVER",
    "S_TEMP",
    "S_HUM",
    "S_BARO",
    "S_WIND",
    "S_RAIN",
    "S_UV",
    "S_WEIGHT",
    "S_POWER",
    "S_HEATER",
    "S_DISTANCE",
    "S_LIGHT_LEVEL",
    "S_ARDUINO_NODE",
    "S_ARDUINO_REPEATER_NODE",
    "S_LOCK",
    "S_IR",
    "S_WATER",
    "S_AIR_QUALITY",
    "S_CUSTOM",
    "S_DUST",
    "S_SCENE_CONTROLLER",
    "S_RGB_LIGHT",
    "S_RGBW_LIGHT",
    "S_COLOR_SENSOR",
    "S_HVAC",
    "S_MULTIMETER",
    "S_SPRINKLER",
    "S_WATER_LEAK",
    "S_SOUND",
    "S_VIBRATION",
    "S_MOISTURE",
    "S_INFO",
    "S_GAS",
    "S_GPS",
    "S_WATER_QUALITY"
    ],
    "internal": [
    "I_BATTERY_LEVEL",
    "I_TIME",
    "I_VERSION",
    "I_ID_REQUEST",
    "I_ID_RESPONSE",
    "I_INCLUSION_MODE",
    "I_CONFIG",
    "I_FIND_PARENT_REQUEST",
    "I_FIND_PARENT_RESPONSE",
    "I_LOG_MESSAGE",
    "I_CHILDREN",
    "I_SKETCH_NAME",
    "I_SKETCH_VERSION",
    "I_REBOOT",
    "I_GATEWAY_READY",
    "I_SIGNING_PRESENTATION",
    "I_NONCE_REQUEST",
    "I_NONCE_RESPONSE",
    "I_HEARTBEAT_REQUEST",
    "I_PRESENTATION",
    "I_DISCOVER_REQUEST",
    "I_DISCOVER_RESPONSE",
    "I_HEARTBEAT_RESPONSE",
    "I_LOCKED",
    "I_PING",
    "I_PONG",
    "I_REGISTRATION_REQUEST",
    "I_REGISTRATION_RESPONSE",
    "I_DEBUG"
    ],
    "subtype":[
    "V_TEMP",
    "V_HUM",
    "V_STATUS",
    "V_PERCENTAGE",
    "V_PRESSURE",
    "V_FORECAST",
    "V_RAIN",
    "V_RAINRATE",
    "V_WIND",
    "V_GUST",
    "V_DIRECTION",
    "V_UV",
    "V_WEIGHT",
    "V_DISTANCE",
    "V_IMPEDANCE",
    "V_ARMED",
    "V_TRIPPED",
    "V_WATT",
    "V_KWH",
    "V_SCENE_ON",
    "V_SCENE_OFF",
    "V_HVAC_FLOW_STATE",
    "V_HVAC_SPEED",
    "V_LIGHT_LEVEL",
    "V_VAR1",
    "V_VAR2",
    "V_VAR3",
    "V_VAR4",
    "V_VAR5",
    "V_UP",
    "V_DOWN",
    "V_STOP",
    "V_IR_SEND",
    "V_IR_RECEIVE",
    "V_FLOW",
    "V_VOLUME",
    "V_LOCK_STATUS",
    "V_LEVEL",
    "V_VOLTAGE",
    "V_CURRENT",
    "V_RGB",
    "V_RGBW",
    "V_ID",
    "V_UNIT_PREFIX",
    "V_HVAC_SETPOINT_COOL",
    "V_HVAC_SETPOINT_HEAT",
    "V_HVAC_FLOW_MODE",
    "V_TEXT",
    "V_CUSTOM",
    "V_POSITION",
    "V_IR_RECORD",
    "V_PH",
    "V_ORP",
    "V_EC",
    "V_VAR",
    "V_VA",
    "V_POWER_FACTOR"
    ],
    command: [
    "PRESENTATION",
    "SET",
    "REQ",
    "INTERNAL",
    "STREAM"
    ],
    "payloadtype":[
    "P_STRING", 
    "P_BYTE", 
    "P_INT16", 
    "P_UINT16", 
    "P_LONG32", 
    "P_ULONG32", 
    "P_CUSTOM", 
    "P_FLOAT32"
    ]};
    
    var match = [
    { re: /^(?:\d+ )?MCO:BGN:INIT (\w+),CP=([^,]+),VER=(.*)/, d: "Core initialization of <b>$1</b>, with capabilities $2, library version $3" },
    { re: /^(?:\d+ )?MCO:BGN:BFR/, d: "Callback before()" },
    { re: /^(?:\d+ )?MCO:BGN:STP/, d: "Callback setup()" },
    { re: /^(?:\d+ )?MCO:BGN:INIT OK,TSP=(.*)/, d: "Core initialized, transport status <b>$1</b>, (1=initialized, 0=not initialized, NA=not available)" },
    { re: /^(?:\d+ )?MCO:BGN:NODE UNLOCKED/, d: "Node successfully unlocked (see signing chapter)" },
    { re: /^(?:\d+ )?!MCO:BGN:TSP FAIL/, d: "Transport initialization failed" },
    { re: /^(?:\d+ )?MCO:REG:REQ/, d: "Registration request" },
    { re: /^(?:\d+ )?MCO:REG:NOT NEEDED/, d: "No registration needed (i.e. GW)" },
    { re: /^(?:\d+ )?!MCO:SND:NODE NOT REG/, d: "Node is not registered, cannot send message" },
    { re: /^(?:\d+ )?MCO:PIM:NODE REG=(\d+)/, d: "Registration response received, registration status <b>$1</b>" },
    { re: /^(?:\d+ )?MCO:PIM:ROUTE N=(\d+),R=(\d+)/, d: "Routing table, messages to node <b>$1</b> are routed via node <b>$2</b>" },
    { re: /^(?:\d+ )?MCO:SLP:MS=(\d+),SMS=(\d+),I1=(\d+),M1=(\d+),I2=(\d+),M2=(\d+)/, d: "Sleep node, duration <b>$1</b> ms, SmartSleep=<b>$2</b>, Int1=<b>$3</b>, Mode1=<b>$4</b>, Int2=<b>$5</b>, Mode2=<b>$6</b>" },
    { re: /^(?:\d+ )?MCO:SLP:TPD/, d: "Sleep node, powerdown transport" },
    { re: /^(?:\d+ )?MCO:SLP:WUP=(-?\d+)/, d: "Node woke-up, reason/IRQ=<b>$1</b> (-2=not possible, -1=timer, >=0 IRQ)" },
    { re: /^(?:\d+ )?!MCO:SLP:FWUPD/, d: "Sleeping not possible, FW update ongoing" },
    { re: /^(?:\d+ )?!MCO:SLP:REP/, d: "Sleeping not possible, repeater feature enabled" },
    { re: /^(?:\d+ )?!MCO:SLP:TNR/, d: " Transport not ready, attempt to reconnect until timeout" },
    { re: /^(?:\d+ )?MCO:NLK:NODE LOCKED. UNLOCK: GND PIN (\d+) AND RESET/, d: "Node locked during booting, see signing documentation for additional information" },
    { re: /^(?:\d+ )?MCO:NLK:TPD/, d: "Powerdown transport" },
    { re: /^(?:\d+ )?TSM:INIT/, d: "Transition to <b>Init</b> state" },
    { re: /^(?:\d+ )?TSM:INIT:STATID=(\d+)/, d: "Init static node id <b>$1</b>" },
    { re: /^(?:\d+ )?TSM:INIT:TSP OK/, d: "Transport device configured and fully operational" },
    { re: /^(?:\d+ )?TSM:INIT:GW MODE/, d: "Node is set up as GW, thus omitting ID and findParent states" },
    { re: /^(?:\d+ )?!TSM:INIT:TSP FAIL/, d: "Transport device initialization failed" },
    { re: /^(?:\d+ )?TSM:FPAR/, d: "Transition to <b>Find Parent</b> state" },
    { re: /^(?:\d+ )?TSM:FPAR:STATP=(\d+)/, d: "Static parent <b>$1</b> has been set, skip finding parent" },
    { re: /^(?:\d+ )?TSM:FPAR:OK/, d: "Parent node identified" },
    { re: /^(?:\d+ )?!TSM:FPAR:NO REPLY/, d: "No potential parents replied to find parent request" },
    { re: /^(?:\d+ )?!TSM:FPAR:FAIL/, d: "Finding parent failed" },
    { re: /^(?:\d+ )?TSM:ID/, d: "Transition to <b>Request Id</b> state" },
    { re: /^(?:\d+ )?TSM:ID:OK,ID=(\d+)/, d: "Node id <b>$1</b> is valid" },
    { re: /^(?:\d+ )?TSM:ID:REQ/, d: "Request node id from controller" },
    { re: /^(?:\d+ )?!TSM:ID:FAIL,ID=(\d+)/, d: "Id verification failed, <b>$1</b> is invalid" },
    { re: /^(?:\d+ )?TSM:UPL/, d: "Transition to <b>Check Uplink</b> state" },
    { re: /^(?:\d+ )?TSM:UPL:OK/, d: "Uplink OK, GW returned ping" },
    { re: /^(?:\d+ )?!TSM:UPL:FAIL/, d: "Uplink check failed, i.e. GW could not be pinged" },
    { re: /^(?:\d+ )?TSM:READY/, d: "Transition to <b>Ready</b> state" },
    { re: /^(?:\d+ )?TSM:READY:SRT/, d: "Save routing table" },
    { re: /^(?:\d+ )?TSM:READY:ID=(\d+),PAR=(\d+),DIS=(\d+)/, d: "Transport ready, node id <b>$1</b>, parent node id <b>$2</b>, distance to GW is <b>$3</b>" },
    { re: /^(?:\d+ )?!TSM:READY:UPL FAIL,SNP/, d: "Too many failed uplink transmissions, search new parent" },
    { re: /^(?:\d+ )?!TSM:READY:FAIL,STATP/, d: "Too many failed uplink transmissions, static parent enforced" },
    { re: /^(?:\d+ )?TSM:FAIL:CNT=(\d+)/, d: "Transition to <b>Failure</b> state, consecutive failure counter is <b>$1</b>" },
    { re: /^(?:\d+ )?TSM:FAIL:PDT/, d: "Power-down transport" },
    { re: /^(?:\d+ )?TSM:FAIL:RE-INIT/, d: "Attempt to re-initialize transport" },
    { re: /^(?:\d+ )?TSF:CKU:OK,FCTRL/, d: "Uplink OK, flood control prevents pinging GW in too short intervals" },
    { re: /^(?:\d+ )?TSF:CKU:OK/, d: "Uplink OK" },
    { re: /^(?:\d+ )?TSF:CKU:DGWC,O=(\d+),N=(\d+)/, d: "Uplink check revealed changed network topology, old distance <b>$1</b>, new distance <b>$2</b>" },
    { re: /^(?:\d+ )?TSF:CKU:FAIL/, d: "No reply received when checking uplink" },
    { re: /^(?:\d+ )?TSF:SID:OK,ID=(\d+)/, d: "Node id <b>$1</b> assigned" },
    { re: /^(?:\d+ )?!TSF:SID:FAIL,ID=(\d+)/, d: "Assigned id <b>$1</b> is invalid" },
    { re: /^(?:\d+ )?TSF:PNG:SEND,TO=(\d+)/, d: "Send ping to destination <b>$1</b>" },
    { re: /^(?:\d+ )?TSF:WUR:MS=(\d+)/, d: "Wait until transport ready, timeout <b>$1</b>" },
    { re: /^(?:\d+ )?TSF:MSG:ACK REQ/, d: "ACK message requested" },
    { re: /^(?:\d+ )?TSF:MSG:ACK/, d: "ACK message, do not proceed but forward to callback" },
    { re: /^(?:\d+ )?TSF:MSG:FPAR RES,ID=(\d+),D=(\d+)/, d: "Response to find parent request received from node <b>$1</b> with distance <b>$2</b> to GW" },
    { re: /^(?:\d+ )?TSF:MSG:FPAR PREF FOUND/, d: "Preferred parent found, i.e. parent defined via MY_PARENT_NODE_ID" },
    { re: /^(?:\d+ )?TSF:MSG:FPAR OK,ID=(\d+),D=(\d+)/, d: "Find parent response from node <b>$1</b> is valid, distance <b>$2</b> to GW" },
    { re: /^(?:\d+ )?TSF:MSG:FPAR INACTIVE/, d: "Find parent response received, but no find parent request active, skip response" },
    { re: /^(?:\d+ )?TSF:MSG:FPAR REQ,ID=(\d+)/, d: "Find parent request from node <b>$1</b>" },
    { re: /^(?:\d+ )?TSF:MSG:PINGED,ID=(\d+),HP=(\d+)/, d: "Node pinged by node <b>$1</b> with <b>$2</b> hops" },
    { re: /^(?:\d+ )?TSF:MSG:PONG RECV,HP=(\d+)/, d: "Pinged node replied with <b>$1</b> hops" },
    { re: /^(?:\d+ )?TSF:MSG:BC/, d: "Broadcast message received" },
    { re: /^(?:\d+ )?TSF:MSG:GWL OK/, d: "Link to GW ok" },
    { re: /^(?:\d+ )?TSF:MSG:FWD BC MSG/, d: "Controlled broadcast message forwarding" },
    { re: /^(?:\d+ )?TSF:MSG:REL MSG/, d: "Relay message" },
    { re: /^(?:\d+ )?TSF:MSG:REL PxNG,HP=(\d+)/, d: "Relay PING/PONG message, increment hop counter to <b>$1</b>" },
    { re: /^(?:\d+ )?!TSF:MSG:LEN,(\d+)!=(\d+)/, d: "Invalid message length, <b>$1</b> (actual) != <b>$2</b> (expected)" },
    { re: /^(?:\d+ )?!TSF:MSG:PVER,(\d+)!=(\d+)/, d: "Message protocol version mismatch, <b>$1</b> (actual) != <b>$2</b> (expected)" },
    { re: /^(?:\d+ )?!TSF:MSG:SIGN VERIFY FAIL/, d: "Signing verification failed" },
    { re: /^(?:\d+ )?!TSF:MSG:REL MSG,NORP/, d: "Node received a message for relaying, but node is not a repeater, message skipped" },
    { re: /^(?:\d+ )?!TSF:MSG:SIGN FAIL/, d: "Signing message failed" },
    { re: /^(?:\d+ )?!TSF:MSG:GWL FAIL/, d: "GW uplink failed" },
    { re: /^(?:\d+ )?TSF:SAN:OK/, d: "Sanity check passed" },
    { re: /^(?:\d+ )?!TSF:SAN:FAIL/, d: "Sanity check failed, attempt to re-initialize radio" },
    { re: /^(?:\d+ )?TSF:CRT:OK/, d: "Clearing routing table successful" },
    { re: /^(?:\d+ )?TSF:LRT:OK/, d: "Loading routing table successful" },
    { re: /^(?:\d+ )?TSF:SRT:OK/, d: "Saving routing table successful" },
    { re: /^(?:\d+ )?!TSF:RTE:FPAR ACTIVE/, d: "Finding parent active, message not sent" },
    { re: /^(?:\d+ )?!TSF:RTE:DST (\d+) UNKNOWN/, d: "Routing for destination <b>$1</b> unknown, sending message to parent" },
    { re: /^(?:\d+ )?!TSF:SND:TNR/, d: "Transport not ready, message cannot be sent" },
    { re: /^(?:\d+ )?TSF:MSG:READ,(\d+)-(\d+)-(\d+),s=(\d+),c=(\d+),t=(\d+),pt=(\d+),l=(\d+),sg=(\d+):(.*)/, d: "<u><b>Received Message</b></u><br><b>Sender</b>: $1<br><b>Last Node</b>: $2<br><b>Destination</b>: $3<br><b>Sensor Id</b>: $4<br><b>Command</b>: {command:$5}<br><b>Message Type</b>: {type:$5:$6}<br><b>Payload Type</b>: {pt:$7}<br><b>Payload Length</b>: $8<br><b>Signing</b>: $9<br><b>Payload</b>: $10" },
    { re: /^(?:\d+ )?TSF:MSG:SEND,(\d+)-(\d+)-(\d+)-(\d+),s=(\d+),c=(\d+),t=(\d+),pt=(\d+),l=(\d+),sg=(\d+),ft=(\d+),st=(\w+):(.*)/, d: "<u><b>Sent Message</b></u><br><b>Sender</b>: $1<br><b>Last Node</b>: $2<br><b>Next Node</b>: $3<br><b>Destination</b>: $4<br><b>Sensor Id</b>: $5<br><b>Command</b>: {command:$6}<br><b>Message Type</b>:{type:$6:$7}<br><b>Payload Type</b>: {pt:$8}<br><b>Payload Length</b>: $9<br><b>Signing</b>: $10<br><b>Failed uplink counter</b>: $11<br><b>Status</b>: $12 (OK=success, NACK=no radio ACK received)<br><b>Payload</b>: $13" },
    { re: /^(?:\d+ )?!TSF:MSG:SEND,(\d+)-(\d+)-(\d+)-(\d+),s=(\d+),c=(\d+),t=(\d+),pt=(\d+),l=(\d+),sg=(\d+),ft=(\d+),st=(\w+):(.*)/, d: "<u><b style='color:red'>Sent Message</b></u><br><b>Sender</b>: $1<br><b>Last Node</b>: $2<br><b>Next Node</b>: $3<br><b>Destination</b>: $4<br><b>Sensor Id</b>: $5<br><b>Command</b>: {command:$6}<br><b>Message Type</b>:{type:$6:$7}<br><b>Payload Type</b>: {pt:$8}<br><b>Payload Length</b>: $9<br><b>Signing</b>: $10<br><b>Failed uplink counter</b>: $11<br><b>Status</b>: $12 (OK=success, NACK=no radio ACK received)<br><b>Payload</b>: $13" },
    ];
    
    
    
    
    new Vue({
       el: "#parser",
       data: function() {
          return {
             source: "",
             parsed: []
          }; 
       },
       methods: {
           selector: function(cmd) {
                  switch (cmd) {
                     case "0": 
                        return "presentation";
                        break;
                     case "1":
                     case "2":  
                        return "subtype";
                        break;
                     case "3":  
                        return "internal";
                        break;
                  }
           },
           match: function(msg) {
                var self = this;
                for (var i=0, len=match.length;i<len; i++) {
                     var r = match[i];
                     if (r.re.test(msg)) {
                          msg = msg.replace(r.re, r.d);
                          msg = msg.replace(/{command:(\d+)}/g, function(match, m1) { return types.command[m1] });
                          msg = msg.replace(/{pt:(\d+)}/g, function(match, m1) { return types.payloadtype[m1] });
                          return msg.replace(/{type:(\d+):(\d+)}/g, function(match, cmd, type) { 
    return types[self.selector(cmd)][type] 
    });
                     }
                }
           },
           parse: function() {
              var self = this;
              var rows = this.source.split("\n");
              this.parsed = _.map(rows, function(r) {
                  var p = r.split(";");
                  if (p.length !== 6) {
                      var desc = self.match(r);
                      
                      return ["","","","",desc?"":"Unknown", r,  desc];
                  }
                 var sel = self.selector(p[2]);
                  var desc = "";
                  if (p[2] == "3" && p[4] == "9") {
                         desc = self.match(p[5]);
    
                  }
                  return  [
                     p[0],
                     p[1],
                     types.command[p[2]],
                     p[3]=="1"?"true":"false",
                     types[sel][p[4]],
                     p[5],
                     desc
                  ];
              }); 
           }      
       }
    });   
    </script>
    


  • Brilliant, THANKS!


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.