WioLoRaWANFieldTester icon indicating copy to clipboard operation
WioLoRaWANFieldTester copied to clipboard

ChirpStack

Open aruznieto opened this issue 3 years ago • 13 comments

Hi, WioLoRaWANFieldTester can be configurated on ChirpStack and get GPS data on this software?

aruznieto avatar Jul 25 '22 07:07 aruznieto

You have in the developper documentation all the information about uplink & downlink payload to manage the computations in your backend connected to ChirpStack. I'm not against an integration with ChirpStack in my backend to make the computation but I do not have any ChripStack instances available for making test.

disk91 avatar Jul 26 '22 09:07 disk91

Ok, I will test it, and If it works, I'll let you know

aruznieto avatar Jul 27 '22 07:07 aruznieto

Hi, it works perfectly on ChirpStack, and the Codec too (only needs change "Decoder" to "Decode").

I have a question, the device is programed to send Downlink Power to Gateaway at any time?

aruznieto avatar Sep 01 '22 09:09 aruznieto

good to know. downlink device RSSI is not sent to gateway, it's calculated by the device (if it is your question) uplink gateway RSSI is sent to server and returned to device I recommand to read the documentation where all of this has been detailed.

disk91 avatar Sep 01 '22 17:09 disk91

@aruznieto nice, so you've done all stuff only on chirpstack side, right? if so are you sending downlink? Would love to see your decoder/encoder shared :-)

hallard avatar Sep 21 '22 16:09 hallard

Hi @hallard, I only the encoder (it's exactly the same that you can see in the DEVELOPMENT.md) removing const from maxHdop and minstats

  function Decode(fPort, bytes, variables) { 
    var decoded = {};
    // avoid sending Downlink ACK to integration (Cargo)
    if (fPort === 1) {
      var lonSign = (bytes[0]>>7) & 0x01 ? -1 : 1;
      var latSign = (bytes[0]>>6) & 0x01 ? -1 : 1;
      
      var encLat = ((bytes[0] & 0x3f)<<17)+
                   (bytes[1]<<9)+
                   (bytes[2]<<1)+
                   (bytes[3]>>7);
    
      var encLon = ((bytes[3] & 0x7f)<<16)+
                   (bytes[4]<<8)+
                   bytes[5];
      
      var hdop = bytes[8]/10;
      var sats = bytes[9];
      
      maxHdop = 2;
      minSats = 5;
      
      if ((hdop < maxHdop) && (sats >= minSats)) {
        // Send only acceptable quality of position to mappers
        decoded.latitude = latSign * (encLat * 108 + 53) / 10000000;
        decoded.longitude = lonSign * (encLon * 215 + 107) / 10000000;  
        decoded.altitude = ((bytes[6]<<8)+bytes[7])-1000;
        decoded.accuracy = (hdop*5+5)/10
        decoded.hdop = hdop;
        decoded.sats = sats;
      } else {
        decoded.error = "Need more GPS precision (hdop must be <"+maxHdop+
          " & sats must be >= "+minSats+") current hdop: "+hdop+" & sats:"+sats;
      }
      return decoded;
    }
      return null;
}

I do not send downlink data but if @disk91 or somebody could share Encoder code It I could test it on ChirpStack.

aruznieto avatar Sep 21 '22 16:09 aruznieto

thanks, I was hoping you send downlink, I know @disk91 will integrate chirpstack in his backend soon

hallard avatar Sep 21 '22 17:09 hallard

OMG just retrieved I had prepared this job in node red, with distance calculation and gateway counts

image

hallard avatar Sep 21 '22 17:09 hallard

And here the function code with data from Chirpstack (so easily transposable to Chirpstack decoder), don't ask me where I found calculation distance function, don't remember, only I had to google, but looks like not so bad :-)

Now need to finish downlink stuff

function distance(lat1, lon1, lat2, lon2) {
    a1 = lat1 * Math.PI/180; // φ, λ in radians
    a2 = lat2 * Math.PI/180;
    d1 = (lat2-lat1) * Math.PI/180;
    d2 = (lon2-lon1) * Math.PI/180;

    a = Math.sin(d1/2) * Math.sin(d1/2) + 
        Math.cos(a1) * Math.cos(a2) * 
        Math.sin(d2/2) * Math.sin(d2/2);
    c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

    return 6371e3 * c; // in metres
}


var b = msg.payload.data;
var data = {};
var txt = "";
var color = "red";

// Get gateways array
var gws = msg.payload.rxInfo;
var minrssi = -999;
var maxrssi = +999;

// Calculate min/max RSSI
for (i=0; i<gws.length; i++) {
    gw = gws[i];
	if (gw.rssi < maxrssi) { maxrssi = gw.rssi; }
	if (gw.rssi > minrssi) { minrssi = gw.rssi; }
} 


// Only port with data
if (msg.payload.fPort == 1) {

    var lonSign = (b[0]>>7) & 0x01 ? -1 : 1;
    var latSign = (b[0]>>6) & 0x01 ? -1 : 1;
    var encLat = ((b[0] & 0x3f)<<17)+(b[1]<<9)+(b[2]<<1)+(b[3]>>7);
    var encLon = ((b[3] & 0x7f)<<16)+(b[4]<<8)+b[5];
    var hdop = b[8]/10;
    var sats = b[9];
    const maxHdop = 2;
    const minSats = 5;
    data.accuracy = (hdop*5+5)/10
    data.hdop = hdop;
    data.sat = sats;
    data.minrssi = minrssi;
    data.maxrssi = maxrssi;
    data.hotspot = gws.length;

    txt = "Hdop="+hdop+"   Sat="+sats;
    // Send only acceptable quality of position to mappers
    if ((hdop < maxHdop) && (sats >= minSats)) {
        // Get gateways array
        var mindist = 9999;
        var maxdist = 0;
        // Get node position        
        data.lat = latSign * (encLat * 108 + 53 ) / 10000000;
        data.lon = lonSign * (encLon * 215 + 107) / 10000000;  
        data.alt = ((b[6]<<8)+b[7])-1000;
        
        // Calculate distance between GW and node
        for (i=0; i<gws.length; i++) {
            gwlat = gws[i].location.latitude;
            gwlon = gws[i].location.longitude;
            node.warn("gwlat=" + gwlat + "  gwlon=" + gwlon);
            
            dist = distance(data.lat,data.lon,gwlat, gwlon);
            node.warn("distance=" + dist);
            if (dist>maxdist) {maxdist=dist;}
            if (dist<mindist) {mindist=dist;}
        } 
        data.mindist = Number(mindist.toFixed(0));
        data.maxdist = Number(maxdist.toFixed(0));

        color ="green";
    }
    msg.payload = data;
    
} else if (msg.payload.fPort == 2) {
    txt = "Request downlink";
    color = "green";
    msg = null;
}

node.status({fill: color,text: txt});
return msg;

hallard avatar Sep 21 '22 17:09 hallard

For the distance you are using "Harvesine Function", this it would be the Encoder function or you mix both?

aruznieto avatar Sep 21 '22 17:09 aruznieto

For now only for decoding going to my dashboard, but will use these calculated data to send thru downlink according @disk91 documentation ASAP

hallard avatar Sep 21 '22 17:09 hallard

Ah! Ok, I calculate the distance after with Python because I need to analyze other parameters too.

aruznieto avatar Sep 21 '22 17:09 aruznieto

and here the working downlink (my node red specific but easy to adapt)

var data = Buffer.alloc(6);
data[0] = msg.fc & 0xFF; // Frame Counter
data[1] = msg.payload.minrssi + 200;
data[2] = msg.payload.maxrssi + 200;
data[3] = (msg.payload.maxdist/250).toFixed(0);
data[4] = (msg.payload.mindist/250).toFixed(0);
data[5] = msg.payload.hotspot;

var newMsg = {}
newMsg.payload = {
    "confirmed": false,
    "fPort": 2,
    "data": Buffer.from(data,'hex').toString('base64')
}

newMsg.topic = msg.topicbase + "/command/down"

return newMsg;

works like a charm, special mention to @disk91, I feel so stupid not seeing sequenceID, because it's just frame count.

hallard avatar Sep 21 '22 20:09 hallard