Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ChirpStack #41

Open
aruznieto opened this issue Jul 25, 2022 · 13 comments
Open

ChirpStack #41

aruznieto opened this issue Jul 25, 2022 · 13 comments

Comments

@aruznieto
Copy link

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

@disk91
Copy link
Owner

disk91 commented Jul 26, 2022

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.

@aruznieto
Copy link
Author

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

@aruznieto
Copy link
Author

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?

@disk91
Copy link
Owner

disk91 commented Sep 1, 2022

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.

@hallard
Copy link
Contributor

hallard commented Sep 21, 2022

@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 :-)

@aruznieto
Copy link
Author

aruznieto commented Sep 21, 2022

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.

@hallard
Copy link
Contributor

hallard commented Sep 21, 2022

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

@hallard
Copy link
Contributor

hallard commented Sep 21, 2022

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

image

@hallard
Copy link
Contributor

hallard commented Sep 21, 2022

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;

@aruznieto
Copy link
Author

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

@hallard
Copy link
Contributor

hallard commented Sep 21, 2022

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

@aruznieto
Copy link
Author

aruznieto commented Sep 21, 2022

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

@hallard
Copy link
Contributor

hallard commented Sep 21, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants