Simulate message from the Gateway => Gateway Bridge



What is the best way to simulate a message from the gateway to the gateway bridge? Picture for clarification.

Thanks in advanced!

Send a package for my gateway bridge

You’d need to write a script that writes some dummy messages following the packet_forwarder protocol (as defined here), and send them through UDP to the lora-gateway-bridge.

May I ask what are you trying to test with this?


We have no gateway and we are trying to simulate how the flow works after the Gateway Bridge receives the message. Is this something dumb to do?


Given that your gateway communicates with the LoRa Gateway Bridge component, which communicates with an MQTT broker, you could basically publish simulated gateway messages direct to the MQTT broker. The format is documented here:


But it seems wrong to skip components (?). Wouldn’t it be best to test the Gateway Bridge instead of skipping it?


No, not at all, but it’ll definitely be some work to do. I was asking because if you needed to test loraserver and lora-app-server only, I’ve got a script that “simulates” the gateway-bridge allowing to send messages through MQTT to the loraserver, exactly what Orne is suggesting.

It’s kind of messy as it was a quick hack to test my own setup, but you can tweak it a bit with your personal keys, macs, etc., to get it going. The sendMessage function acts as an RX message from the gateway-bridge only, but it should be fairly easy to add a stats message, just check the data formats at Orne’s link. Check it here.

The gateway to lora-gateway-bridge communication is usually kind of straight forward, and once you get a gateway you’ll have to configure the packet forwarder anyway. But again, you may simulate the packet_forwarder if you like.


Hi! Thank you so much for that script.

One question. Where do I specify:

  1. RX1 delay
  2. RX1 data-rate offset
  3. RX2 data-rate
  4. RX2 channel frequency

In the script?


Those are setup at the loraserver end, not per message. See


Thank you! One last question.

I seem to have some trouble with the payload. The error message comes from here:

Seems some of the payload does not comply with cayenne (?). The error itself:

Error: time="2018-02-14T18:02:01Z" level=error msg="decode payload error" application_id=1 codec=CAYENNE_LPP dev_eui=1616161616161616 error="invalid data type: 20" f_cnt=0 f_port=1.

Seems to have something to do with mPayload and when the temperature generateTemp1byte is appended (?)

Generated mPayload: [0 20 0 208 115 108 192 205 199 187 192 5]

Thank you so much for all your help.


Sorry, It doesn’t, I don’t even know what the Cayenne format is . As I mentioned, this works for my setup, where I use 2’s complement to encode different types of values depending on the amount of bytes, data type and min/max values, generating the bytes array following something like this:

    func GenerateSomeFloat(originalFloat float32) []byte {
        encodedFloat := uint32( (originalFloat / maxValue) * float32(math.Pow(2, 31)) )
        byteArray := make([]byte, 4)
        binary.BigEndian.PutUint32(byteArray, encodedFloat)
        return byteArray

The uints and arrays sizes depend of course in how many bytes you are using to represent your value. If you are interested, our general format is based on this GPS encoding format from Multitech.

Then, at lora-app-server, I decode like this (note that I have implemented what we call “data types” that define for example that a Latitude is a 4 bytes float that allows negatives, ranging from -90.0 to 90.0):

func ReadFloatData(dataType DataType, dataArray []byte) (float64, error) {
	if dataType.NumBytes != int32(len(dataArray)) {
		return 0.0, ErrNumBytes

	intData := new(big.Int)

	//Precision is given by the max repesentable number minus 1.
	precision := float64((dataType.NumBytes * 8) - 1)
	var fData float64

	floatInt, _ := new(big.Float).SetInt(intData).Float64()

	if dataType.AllowsNegative {
		fData = (floatInt / (math.Pow(2, precision) - 1.0)) * dataType.MaxVal
		if fData > dataType.MaxVal {
			fData = (2*dataType.MaxVal - fData) * -1.0

	} else {
		//If no negatives are allowd, we don't need a sign bit, so we divide by the whole precision.
		fData = (floatInt / math.Pow(2, precision+1)) * dataType.MaxVal
		if fData > dataType.MaxVal {
			return 0.0, ErrDataTypeRange

	//Check for min val, return n error if the value is outside the range.
	if fData < dataType.MinVal {
		return 0.0, ErrDataTypeRange

	return fData, nil


In summary, if you want to use the Cayenne encoding, then you’ll need to generate your bytes array payload following that format, not with the generateSomtehing functions at the script which follow our own encoding.


Sorry, I missed the link. You could use it to create the byte arrays you are looking for, or maybe some other library like this or this to pre-encode some sample data and then hardcode it to the script.


Again, thank you so much!! You are a lifesaver.

I knew I have seen Cayenne somewhere. I picked Cayenne as predefined payload codec for my test-application in the GUI.


Hello guys, I’m trying to fix a problem because I want to simulate a GW/node and I have the Lora server configurated and I have another virtual machine to be my ‘‘gateway’’.
Someone can explain how can I install that to Send a package for my gateway bridge?
Did you installed in LoRaServer the script? And also did you install the gateway bridge in the same machine you have the loraserver run?
I’m trying to get a GW+Node simulator and I can’t :frowning: I see this topic so maybe can help me


Hi, @dicarva. If you are referring to my script, as I mentioned, it’s a bit messy and outdated. I’ve been meaning to rewrite it properly, maybe if I get some time this or next week I’ll get to it. I’ll post it here if any modifications are made.

Anyway, the important thing is that it’s not to be installed over anything else -it’s just a simple script that may be compiled and executed by itself-, and its location doesn’t matter. So you’d need to clone the repo (or copy the file, whatever you like), modify the source to adjust it for your needs (change gw mac, device keys, etc.) and point it to wherever your mosquitto broker is, the just go build and run it.

Good luck!


How you did you point to Mosquitto broker?


Check the file lora-node.go, it’s there. You need to change these lines with you mosquitto location and credentials (if any):

    opts := MQTT.NewClientOptions()


lora-node.go:12:2: cannot find package “” in any of:
/usr/src/ (from $GOROOT)
/home/diogo/go/src/ (from $GOPATH)
lora-node.go:13:2: cannot find package “” in any of:
/usr/src/ (from $GOROOT)
/home/diogo/go/src/ (from $GOPATH)

he show me this error bit I won’t to install because I already have the loraserver


You need to fetch those packages first because the script depends on them. From the terminal:

go get
go get

That said, please take a careful look at the script and modify anything you need to before using it. As I mentioned, it’s outdated (anything could be broken) and pretty cusomized to our test scenario.



./lora-node.go:320:4: error: unknown field ‘AppEUI’ in ‘lorawan.JoinRequestPayload’
AppEUI: appEUI,
./lora-node.go:326:19: error: reference to undefined field or method ‘SetMIC’
if err := joinPhy.SetMIC(appKey); err != nil {
./lora-node.go:355:4: error: unknown field ‘AppEUI’ in ‘lorawan.JoinRequestPayload’
AppEUI: appEUI,
./lora-node.go:361:19: error: reference to undefined field or method ‘SetMIC’
if err := joinPhy.SetMIC(appKey); err != nil {
./lora-node.go:407:15: error: reference to undefined field or method ‘SetMIC’
if err := phy.SetMIC(nwkSKey); err != nil {
./lora-node.go:319:15: error: incompatible type for field 2 in struct construction (type has no methods)
MACPayload: &lorawan.JoinRequestPayload{
./lora-node.go:354:15: error: incompatible type for field 2 in struct construction (type has no methods)
MACPayload: &lorawan.JoinRequestPayload{
./lora-node.go:396:12: error: incompatible type for field 4 in struct construction
FOpts: []lorawan.MACCommand{}, // you can leave this out when there is no MAC command to send

This is normal?


Ah, well, there you go, it is indeed outdated and tries to use some old definitions from Orne’s lorawan package that no longer exist. But still, you could check and try to reimplement what has changed at the script (I’m not able to do it right now, maybe in a couple of days or next week).