Raw on demand - 2CVS & IOTEdge

Hi @Bhaskar ,

we have a 2 Channel Vib Sen Plus. We want to get processed data and raw on demand. I’ve got it working with a node-red flow on the IoTEdge Computer. Works fine for processed, but how can I request the raw data?

I’ve tried to reproduce it like you do in this video IoT Vibration And Temperature sensor for Continuous Machine Health Monitoring - YouTube But it will not work. May be it depends in the Zigmo Modem which I do not have. I can’t get the magic out of the flow of Industrial-IoT-Wireless-Vibration-Sensor/PR55-61_N_Type_81.json at main · ncd-io/Industrial-IoT-Wireless-Vibration-Sensor · GitHub

Is there a way to handle the raw-on-demand with Sensor & IOTEdge? If not, what do I need? Attach a MegaModem to the IOTEdge? :slight_smile:

And how to trigger it without clicking the Inject Button?

Regards and thanks,

Tom

Hi Tom,

You will need to make sure the sensor is configured for(Raw Data on Demand) first. Then you can use this flow to request Raw Time Domain data from the sensor:

[{"id":"f8778ff4.caf6b","type":"tab","label":"V3 Raw On Demand","disabled":true,"info":""},{"id":"6ee4f293.482d3c","type":"inject","z":"f8778ff4.caf6b","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"devices\":[\"00:13:a2:00:41:b1:72:47\"]}","payloadType":"json","x":550,"y":300,"wires":[["efaab95f.f76e48"]]},{"id":"efaab95f.f76e48","type":"function","z":"f8778ff4.caf6b","name":"Add incomming device to context","func":"var newDevices = msg.payload.devices;\nvar existingDevices = flow.get('devices');\n\nif(typeof existingDevices == 'undefined'){\n    flow.set('devices',newDevices);\n    msg.payload.devices = newDevices;\n    return msg;\n}else{\n    for(let newDevice of newDevices){\n        exists = false;\n        for(let existingDevice of existingDevices){\n            if(newDevice == existingDevice){\n                exists = true;\n                break;\n            }\n        }\n        if(!exists){\n            existingDevices.push(newDevice);\n        } \n    }\n}\nflow.set('devices',existingDevices);\nmsg.payload.devices = existingDevices;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":820,"y":300,"wires":[[]]},{"id":"9da7fd56.80fbb","type":"function","z":"f8778ff4.caf6b","name":"Check Devices","func":"var devices = flow.get('devices');\nvar deviceID = msg.payload.addr;\nif(typeof devices == 'undefined')return;\n\nfor(i = 0; i < devices.length; i++){\n    // console.log('device: '+devices[i]+' deviceID: '+deviceID);\n    if(deviceID == devices[i]){\n        msg.payload.address = deviceID;\n        // msg.payload.address = \"00:00:00:00:00:00:ff:ff\"\n        msg.payload.data = [0xF8,0x99,0x00,0x00,0x28];\n        devices.splice(i,1);\n        return msg;\n    }\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":360,"wires":[["a86ae21.e9b19a","e5aca4b6.98e108"]]},{"id":"e6d5abf2.b40d8","type":"switch","z":"f8778ff4.caf6b","name":"Vibration Check Valve","property":"payload.sensor_type","propertyType":"msg","rules":[{"t":"eq","v":"82","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":640,"y":540,"wires":[["9da7fd56.80fbb","831654f9.5c3818"]]},{"id":"a86ae21.e9b19a","type":"delay","z":"f8778ff4.caf6b","name":"","pauseType":"delay","timeout":"100","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"outputs":1,"x":130,"y":540,"wires":[["b673600b6bff4b6f"]]},{"id":"831654f9.5c3818","type":"debug","z":"f8778ff4.caf6b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":870,"y":540,"wires":[]},{"id":"e5aca4b6.98e108","type":"debug","z":"f8778ff4.caf6b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":670,"y":360,"wires":[]},{"id":"53605b351d6c1b85","type":"ncd-wireless-node","z":"f8778ff4.caf6b","name":"","connection":"b99bad4c7fc89c79","config_comm":"b99bad4c7fc89c79","addr":"00:13:a2:00:41:c9:43:3c","sensor_type":"82","auto_config":true,"node_id_delay_active":true,"node_id":0,"delay":300,"destination":"0000FFFF","power_active":"","power":4,"retries_active":"","retries":10,"pan_id_active":"","pan_id":"7FFF","change_enabled":"","change_pr":"0","change_interval":"0","cm_calibration":"60.6","bp_altitude":"0","bp_pressure":"0","bp_temp_prec":"0","bp_press_prec":"0","amgt_accel":"0","amgt_mag":"0","amgt_gyro":"0","impact_accel":"0","impact_data_rate":"4","impact_threshold":25,"impact_duration":1,"activ_interr_x":1,"activ_interr_y":2,"activ_interr_z":4,"activ_interr_op":8,"force_calibration_co2_auto_config":"","force_calibration_co2":400,"filtering":0,"data_rate":5,"time_series":0,"reading_type":1,"mode_80_active":"","mode_80":0,"filter_80_active":"","filter_80":0,"output_data_rate_101_active":"","output_data_rate_101":0,"sampling_duration_101_active":"","sampling_duration_101":1,"sampling_interval_101_active":true,"sampling_interval_101":1,"full_scale_range_101_active":"","full_scale_range_101":1,"x_axis_101":"","y_axis_101":"","z_axis_101":"","x":580,"y":780,"wires":[[]]},{"id":"b673600b6bff4b6f","type":"ncd-gateway-node","z":"f8778ff4.caf6b","name":"","connection":"f3d2780c.9b91b","unknown_devices":0,"outputs":1,"x":370,"y":540,"wires":[["e6d5abf2.b40d8"]]},{"id":"b99bad4c7fc89c79","type":"ncd-gateway-config","name":"Zigmo_11_15","comm_type":"serial","ip_address":"","tcp_port":"2101","port":"/dev/tty.usbserial-AC3VPU1B","baudRate":"115200","pan_id":"7fff","rssi":true},{"id":"f3d2780c.9b91b","type":"ncd-gateway-config","name":"Zigmo","comm_type":"serial","ip_address":"","tcp_port":"2101","port":"/dev/tty.usbserial-AC3VPU1B","baudRate":"115200","pan_id":"7fff","rssi":false}]

This flow uses a global variable which can store a list of sensor addresses. If a sensor checks in and the sensor’s address is in the global array then a request will be sent to request raw time domain data, then the sensor will respond with the Raw Data.

To test you will need to alter the address sent by the inject node to send the address of your sensor.

Let me know if you have any questions on this.

Thank you,
Travis Elliott

Hi, thanks.

I think I’ve got it working.
image

With a mix of your flow and some part of the Github Repo and testing. Need Vibration Check Valve for 81 instead of 82

And the Check Device for the 2 Channel Sensor needs other bytes for the probes.

msg.payload.data = [0xF4,0x4F,0x00,0x00,0x50,0x13,0x01]; // type 81 probe one
// msg.payload.data = [0xF4,0x4F,0x00,0x00,0x50,0x13,0x02]; // type 81 probe two

But how to get both sensors as RAW data? It’s the 2 Channel Vibration Sensor.

I think the “probe” is the difference, right? I was not able to do two parallel “Check Devices” each for a separate probe. To receive for both sensors the rawdata.

– Tom

Hi Tom,

Yes, sorry, that flow was created for a single probe sensor. I was honestly not aware that the dual probe sensor comes in as two transmissions. @Bhaskar can you comment on how raw data works for the 2 probe V3?

1 Like

With this payload I’m able to retrieve the data, but I don’t know how to get them both, may be with to sensor_data raw responses. With the “Check Devices” function I just can trigger one msg.

Hi Tom,

Can you paste the data object you are receiving back from the device when requesting RAW data here?

I’ve reduced the data array, it contains 160 entries.

{
  "topic": "sensor_data",
  "data": {
    "nodeId": 0,
    "firmware": 4,
    "battery": "3.29",
    "battery_percent": "99.64",
    "counter": 3,
    "sensor_type": 81,
    "sensor_data": {
      "probe": "1",
      "time_id": "13:25",
      "mac_address": "00:13:a2:00:41:e3:9e:f7",
      "en_axis": 7,
      "fsr": "16g",
      "odr": 800,
      "device_temp": 22.3,
      "data": {
        "1": {
          "x": -0.52136,
          "y": -1.57241,
          "z": -0.67424
        },
        "2": {
          "x": -0.52136,
          "y": -1.57241,
          "z": -0.62867
        },
        "3": {
          "x": -0.52136,
          "y": -1.57241,
          "z": -0.62867
        },
        "4": {
          "x": -0.56644,
          "y": -1.617,
          "z": -0.62867
        },........
        ........
        ........ 160 entires
      }
    },
    "sensor_name": "Two Channel Vibration Plus",
    "type": "sensor_data",
    "addr": "00:13:a2:00:41:e3:9e:f7",
    "received": 1649165116819,
    "original": {
      "mac": "00:13:a2:00:41:e3:9e:f7",
      "receive_options": {
        "ack": 1,
        "broadcast": 1,
        "type": "DigiMesh"
      },
      "data": [
        127,
        0,
        4,
        3,
        255,
        3,
        0,
        81,
        0,
        1,
        10,
        199,
        13,
        25,
        8,
        182,
        6,
        6,
        119,
        250,
        253,
        251,
        216,
        243,
        119,
        250,
        160,
        251,
        216,
        243,
        119,
        250,
        160,
        251,
        216,
        243,
        28,
        250,
        253,
        251,
        216,
        243,
        119,
        250,
        160,
        251,
        216,
        243,
        211,
        250,
        253,
        251,
        216,
        243,
        119,
        250,
        160,
        251,
        216,
        243,
        119,
        250,
        67,
        251,
        216,
        243,
        119,
        250,
        253,
        251,
        216,
        243,
        119,
        250,
        253,
        251,
        216,
        243,
        28,
        250,
        67,
        251,
        216,
        243,
        119,
        250,
        67,
        251,
        216,
        243,
        119,
        250,
        160,
        251,
        216,
        243,
        119,
        250,
        253,
        251,
        216,
        243,
        119,
        250,
        253,
        251,
        216,
        243,
        119,
        250,
        253,
        251,
        216,
        243,
        119,
        250,
        160,
        251,
        216,
        243,
        119,
        250,
        253
      ],
      "rssi": {},
      "type": "receive_packet"
    },
    "rssi": 70,
    "modem_mac": "00:13:A2:00:41:E3:9E:CF"
  },
  "payload": {
    "probe": "1",
    "time_id": "13:25",
    "mac_address": "00:13:a2:00:41:e3:9e:f7",
    "en_axis": 7,
    "fsr": "16g",
    "odr": 800,
    "device_temp": 22.3,
    "data": {
      "1": {
        "x": -0.52136,
        "y": -1.57241,
        "z": -0.67424
      },
      "2": {
        "x": -0.52136,
        "y": -1.57241,
        "z": -0.62867
      },
      "3": {
        "x": -0.52136,
        "y": -1.57241,
        "z": -0.62867
      },
      "4": {
        "x": -0.56644,
        "y": -1.617,
        "z": -0.62867
      },........
      ........
      ........160 entires
    }
  },
  "_msgid": "d098ffb6.82aff"
}

And this is my “Check Device” Function

var devices = flow.get('devices');
var ramdevices = flow.get('ramdevices');
var deviceID = msg.payload.addr;
if(typeof devices == 'undefined')return;
if(typeof ramdevices == 'undefined'){
    ramdevices = [];
    flow.set('ramdevices',ramdevices);
    
}

for(i = 0; i < devices.length; i++){
    // console.log('device: '+devices[i]+' deviceID: '+deviceID);
    if(deviceID == devices[i] && msg.payload.sensor_data.hasOwnProperty("x1_rms_ACC_G")){
        if(ramdevices.includes(deviceID)){
          msg.payload.address = deviceID;  
        }
        else{
           msg.payload.address = "00:00:00:00:00:00:ff:ff" ;
           ramdevices.push(deviceID);
        }
        msg.payload.data = [0xF4,0x4F,0x00,0x00,0x50,0x13,0x01]; // type 81 probe one
        flow.set("ramdevices",ramdevices);
        
        
        var msg2 = JSON.parse(JSON.stringify(msg));       
        msg2.payload.data = [0xF4,0x4F,0x00,0x00,0x50,0x13,0x02]; // type 81 probe two
        
        // Just for me for a quicker look
        msg2.identity="probe2";
        msg.identity="probe1";
        
        return [msg,msg2];
    }
}

If I change the order from return [msg,msg2]; to return [msg2,msg];, probe2 is returned

I’ve fixed it to send both messages to the same output like

return [[msg,msg2]]; but also not the trick.

It may be necessary to send the message to request probe 1 raw data when the parsed message is received, then once the message containing probe 1 raw data is received then send the request for Probe 2 raw data.

I also wonder if you sent 0x03 instead of 0x01/0x02 if both probes would be sent. I would have to dig deeper to find out if the sensor supports that but it’s a simple test you could try.

returns / does noting. I’ve tried it.

You might try sending a second request to read probe 2 after receiving raw data for probe 1 then. Otherwise we will need to wait for @Bhaskar to comment further on this capability.

:slight_smile: this is what I’ve done. It runs the round till “trigger P2” logs the output. But the Raw is not coming for it.

Will wait for a hint of Bhaskar

The way I’ve written up our Node-Red flows is that you can request a RAW sample from Probe 1 or Probe 2.

The requests gets added to a context variable array.

When a processed sample comes in for the sensor for which there is a request against either probe, the request for RAW is sent.

The request is sent for whichever Probe is found first in the array, but only for one of them.
When the RAW request then comes in (lets say we requested RAW for HEAD1, and we receive RAW for HEAD1), the context variable containing the request for HEAD1 is then deleted.

The next time the sensor transmits its Processed data, it will fulfill the remaining request (RAW for HEAD2 for example).

Long winded way of saying, I think you can only request RAW from one head at a time. You will need to wait until the next Processed comes in to request against the other head.

3 Likes

Hi kstokes,

yes, that’s what I am doing right now. i take the corresponding raw value at each processed data and change the last byte after each pass to get the other raw samples at the next pass. Works for now, but not much elegant.