Nemeus NIS-UL – Ultrasonic sensor

Thanks sir, I have thought about resetting it by holding the magnet for 20 sec, but won’t this reset the configuration also?, and unfortunately, these sensors were shipped configured and i don’t think we know how to reconfigure them again.

At that time, i think it was by re creating the app. but i am not sure

1 Like

Hi @habibraed ,

Using hardware reset doesn’t clear the configuration of the device, but does reset the session keys. No other options cause a Join message to be sent, so this is the only choice except maybe leaving the battery out, but flash storage would survive this and supercapacitors can complicate the process.

You must make sure you get your keys correct in the application, but for a quick check you can see the join attempt in the gateway traffic console.


Hi Ben, thanks so much for your help. It finally worked…
What i did is i let the newly created app generate the Dev EUI, at that moment i could see the join attempt in he gateway traffic and i could see that it has failed, then i manually modified the Dev EUI back to the sensors specific, the join was successful and the app worked.

I just have a quick question regarding the coverage, it seems that the sensor only work when it is extremly close to the gateway, i have tested the battery level and it looks fine.
I have contacted nemeus regarding this, and they send us a few models for an external antenna, but their seems no where to connect a SMA connecter on the PCB once i opened the sensor, is their some sort of modification needs to be done ?


@habibraed great news that you are back online!

We have had no range problems with the NIS-UL like that you describe. The external antenna model is currently being tested by a client and comes with a bulkhead SMA connector. The other versions I assume have a PCB or ceramic antenna but have achieved several km range without problems. Perhaps you have a faulty device? Is it an 868MHz model? Also be sure your gateway is multi-channel or you’ll be missing many messages.

Hi Ben,
Thanks again, We have a multitech outdoor unit, and i think all chanels are enabled, or atleast when i ran the ttn packet forwarder script i think it showed that.

and yes we have the 868MHz model


I am a novice, I own the NIS-UL - ultrasonic sensor - Nemeus and I want a script following a routing.
Can you help me thanks.

Hi Serge, the script @arjanvanb wrote works if you put it into the decoder in your application.

The rest of the setup is documented here

If you need help on where to apply the decoder code then let me know.


I am looking for a PHP script
Only, I do not know anything about PHP programming.
Thank you

I am sorry Serge, but this forum is not the right place to ask questions about PHP programming.

I think @BoRRoZ has a fair point. The end application is quite an important part of the process, but probably not for here. If you’re a novice then I’d recommend using the decoder to make the fields easier to work with. Arjan has done a great job in splitting them into human readable fields for posting, otherwise you’ll have the additional problem of learning bitwise operations in PHP.

1 Like

Ok about PHP.
I am proud to say that I could this question.

CLICK to see code

function Decoder(bytes, port) {
  // See
  // Test with:
  //   8B 02 0097 0098 1f 19: 151, 152cm; 31, 25°C
  //   8B 02 0097 0098 fe 03: 151, 152cm; -2, 3°C
  //   AF 03 0097 0098 0090 0fb9 0e91 0fff fe 03 00 0a: 151, 152, 144cm; 4025, 3729, 4095mV, -2, 3, 0°C
  //   82 00a0: 160cm
  //   88 1e: 30°C
  var usonic_dist = [], voltage = [], internal_temp = [];
  var i = 0, m = 0;

  var mask = bytes[i++];

  // If bit 0 set: 1 byte indicating the number of measurements, else 1
  var nb_meas = mask & 1<<0 ? bytes[i++] : 1;

  // If bit 1 set: distances in centimeters, each 2 bytes unsigned MSB, 1 to 300cm
  if (mask & 1<<1) {
    for (m = 0; m < nb_meas; m++) {
      usonic_dist.push(bytes[i++]<<8 | bytes[i++]);

  // If bit 2 set: voltages in millivolts, each 2 bytes unsigned MSB
  if (mask & 1<<2) {
    for (m = 0; m < nb_meas; m++) {
      voltage.push((bytes[i++]<<8 | bytes[i++]) / 1000);

  // If bit 3 set: internal temperatures, each 1 byte signed integer [-128..+127]
  if (mask & 1<<3) {
    for (m = 0; m < nb_meas; m++) {
      // Sign-extend to 32 bits to support negative values, by shifting 24 bits
      // (too far) to the left, followed by a sign-propagating right shift:

  // Bit 4: reserved

  // If bit 5 set: cause for the measurement, else "periodic measurement"
  var cause = mask & 1<<5 ? bytes[i++] : 1;

  // We should have consumed all bytes, if not then just return the payload as hex
  if (i !== bytes.length) {
    return {
      'error': 'failed to parse payload',
      'payload': {
         return ('0' + b.toString(16).toUpperCase()).substr(-2);
       }).join(' ')
  // Format the results
  var result = {};
  // Show all 8 bits, ensuring leading zeroes
  result.mask = '0b' + ('00000000' + mask.toString(2)).substr(-8);

  result.numberOfMeasurements = nb_meas;
  result.distances = usonic_dist;
  result.voltages = voltage;
  result.temperatures = internal_temp;

  // Same data, grouped by measurement
  result.measurements = [];
  for (m = 0; m < nb_meas; m++) {
      distance: usonic_dist[m],
      voltage: voltage[m],
      temperature: internal_temp[m]

  result.cause = cause;
  result.causeMask = '0b' + ('00000000' + cause.toString(2)).substr(-8);
  result.causes = [];
  if (cause & 1<<0) {
  if (cause & 1<<1) {
    result.causes.push('usonic_dist > high threshold');
  if (cause & 1<<2) {
    result.causes.push('usonic_dist < high threshold - high hysteresis');
  if (cause & 1<<3) {
    result.causes.push('usonic_dist < low threshold');
  if (cause & 1<<4) {
    result.causes.push('usonic_dist > low threshold + low hysteresis');
  if (cause & 1<<5) {
    result.causes.push('forced manually');

  return result;
  "mask": "0b10101111",
  "numberOfMeasurements": 3,
  "distances": [
  "voltages": [
  "temperatures": [
  "measurements": [
      "distance": 151,
      "voltage": 4.025,
      "temperature": -2
      "distance": 152,
      "voltage": 3.729,
      "temperature": 3
      "distance": 144,
      "voltage": 4.095,
      "temperature": 0
  "cause": 10,
  "causeMask": "0b00001010",
  "causes": [
    "usonic_dist > high threshold",
    "usonic_dist < low threshold"


Can I ask how to configure this script as it is on this forum?

Thank you


  1. go to your application on The Things Network Console and select Payload Formats:

  2. Paste it into the Decoder using the Custom decoder type:

  3. Now save it:

  4. You can test if it worked by pasting made up payloads into the test payload area:

  5. You can see your own payloads arriving with decoded data under the Data tab:

Bonne chance!


I will do some tests.
Thank you

Is anyone sent the downlink message successfully to the device?
I want to let the device send an uplink message every 10 minutes.

I used this message but it failed,
Hex: “028E01580201100100”
Base64: “Ao4BWAIBEAEA”
If the message is false can you recommend to me the true message to send uplink every 10m with only one reading?