Esempio n. 1
0
    def post(self, deviceUid=None):
        if (deviceUid):
            log.info("Posted data for device #%s" % deviceUid)

        frame = None
        if (request.content_type.startswith('application/json')):
            log.info("Received a json LPP: %s" % request.json)
            args = parser.parse_args(strict=True)
            log.info("JSON payload: %s" % json.dumps(args))
            lppBase64Payload = args['lpp']
            frame = LppFrame().from_base64(lppBase64Payload)

        elif (request.content_type.startswith('application/octet-stream')):
            lppBinaryPayload = request.data
            log.info("Received a binary LPP: %s" % lppBinaryPayload)
            frame = LppFrame().from_bytes(lppBinaryPayload)
            #lppPayload = ''.join(["%02x" % char for char in lppData])
            #log.info("Hex LPP in string format: %s" % lppPayload)

        if (deviceUid and frame):
            log.info("Frame LPP: %s" % frame)
            try:
                processLpp(deviceUid, frame)
            except Exception as e:
                log.error('Error trying to process LPP !', exc_info=e)
                abort(400, "Unable to process LPP !")

        return {"message": "ok"}
Esempio n. 2
0
def uplink_callback(msg, client):
    print("Uplink message")
    print("  FROM: ", msg.dev_id)
    print("  TIME: ", msg.metadata.time)
    print("   RAW: ", msg.payload_raw)
    with open(f_logging, 'a') as fl:
        print(str(msg), file=fl)
    frame = LppFrame.from_base64(msg.payload_raw)
    for d in frame.data:
        print("  DATA:", d)
    lat = frame.data[0].value[0]
    lon = frame.data[0].value[1]
    location = {
        "name": msg.dev_id,
        "description": "Continuously updated GPS location of tracker device",
        "encodingType": "application/vnd.geo+json",
        "location": {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [lon, lat]
            }
        }
    }
    print("  POST values: ", str(location))
    if msg.dev_id in dev_urls:
        print("  POST URL: ", dev_urls[msg.dev_id]['url'])
        r = requests.post(dev_urls[msg.dev_id]['url'], json=location)
        print("  POST status: %d" % r.status_code)
    else:
        print("  invalid device: ", msg.dev_id)
Esempio n. 3
0
def sen
    frame = LppFrame()
    frame.add_temperature(0, raw_temp)
    frame.add_humitidy(1, humidity)
    frame.add_pressure(2, pressure)
    frame.add_

    buffer = frame.bytes()

    #print(buffer)

    lora = Rak811()
    lora.hard_reset()
    lora.mode = Mode.LoRaWan
    lora.band = 'EU868'
    lora.set_config(app_eui='70B3D57ED001C921',
                app_key='55B77F583763DCFE02AC75DB77CDD4B1')
    lora.join_otaa()
    lora.dr = 5
    lora.send(bytes(buffer))
    lora.close()
Esempio n. 4
0
def test_uplink_system_temperature(network_lora, caplog):
    """
    Pretend to invoke the datalogger on a LoPy4 with basic system sensors.
    Effectively, only the "system.temperature" sensor will be transmitted
    over LoRa telemetry.

    By intercepting the lora socket communication, proof that the
    submitted payload is correct by checking the raw payload value
    and decoding it through Cayenne.
    """

    # Define artificial LoRa conversation.
    network_lora.register_conversation()

    # Invoke datalogger with LoRaWAN telemetry settings for a single duty cycle.
    from test.settings import telemetry_lorawan
    invoke_datalogger_pycom(caplog, settings=telemetry_lorawan)

    # Capture log output.
    captured = caplog.text

    # Proof it works by verifying log output.
    assert "Starting Terkin datalogger" in captured, captured
    assert "platform: LoPy4" in captured, captured
    assert "[LoRa] Starting LoRa Manager" in captured, captured
    assert "Telemetry transport: CayenneLPP over LoRaWAN/TTN" in captured, captured
    assert "Telemetry status: SUCCESS (1/1)" in captured, captured

    # Check the raw LoRa payload.
    from mocket import Mocket
    assert Mocket.last_request() == bytearray(b'\x00g\x01\xbf\x00\x01\x00')

    # Check the value after decoding from CayenneLPP.
    from cayennelpp import LppFrame
    data = LppFrame.from_bytes(Mocket.last_request()).data

    # System temperature
    assert data[0].channel == 0
    assert data[0].type == 103
    assert data[0].value == (44.7, )

    # EOF?
    assert data[1].channel == 0
    assert data[1].type == 1
    assert data[1].value == (0, )

    assert "[LoRa] No downlink message processed" in captured, captured
    def to_cayenne_lpp_ratrack(self):
        """
        Serialize plain data dictionary to binary CayenneLPP format.
        """
        data = self.data

        from cayennelpp import LppFrame
        # create empty frame
        frame = LppFrame()


        channel = 1
        # add some sensor data
        if 'temperature' in data:
            try:
                frame.add_temperature(channel, data.get('temperature'))
            except:
                log.exception('[Cayenne] Serialization failed')

        #if 'humidity' in data:
        #    try:
        #        frame.add_humitidy(channel, data.get('add_humidity'))
        #    except:
        #        log.exception('[Cayenne] Serialization failed')

        if 'pressure' in data:
            try:
                frame.add_barometer(channel, data.get('pressure'))
            except:
                log.exception('[Cayenne] Serialization failed')

        if 'speed' in data and 'roll' in data and 'pitch' in data:
            try:
                frame.add_gyrometer(channel, data.get('speed'), data.get('roll'), data.get('pitch'))
            except:
                log.exception('[Cayenne] Serialization failed')

        if 'battery_voltage' in data:
            try:
                frame.add_analog_input(channel, data.get('battery_voltage'))
            except:
                log.exception('[Cayenne] Serialization failed')

        if 'latitude' in data and 'longitude' in data and 'altitude' in data:
            try:
                log.info('GPS to Cayenne')
                frame.add_gps(channel, data.get('latitude'), data.get('longitude'), data.get('altitude'))
            except:
                log.exception('[Cayenne] Serialization failed')

        #channel = 2
        #if 'cog' in data:
        #    try:
        #        frame.add_analog_input(channel, data.get('cog'))
        #    except:
        #        log.exception('[Cayenne] Serialization failed')

        channel = 3
        if 'memfree' in data:
            try:
                frame.add_analog_input(channel, data.get('memfree'))
            except:
                log.exception('[Cayenne] Serialization failed')

        channel = 4
        if 'waterlevel_volt' in data:
            try:
                frame.add_analog_input(channel, data.get('waterlevel_volt'))
            except:
                log.exception('[Cayenne] Serialization failed')

        channel = 5
        if 'moisture_volt' in data:
            try:
                frame.add_analog_input(channel, data.get('moisture_volt'))
            except:
                log.exception('[Cayenne] Serialization failed')

        return frame.bytes()
Esempio n. 6
0
# Most of the setup should happen only once...
print('Setup')
lora.hard_reset()
lora.mode = Mode.LoRaWan
lora.band = 'EU868'
lora.set_config(dev_addr="",
                apps_key="",
                nwks_key="")


print('Joining')
lora.join_abp()
# Note that DR is different from SF and depends on the region
# See: https://docs.exploratory.engineering/lora/dr_sf/
# Set Data Rate to 5 which is SF7/125kHz for EU868
lora.dr = 5



while True:
    frame = LppFrame()
    print("addgps")
    frame.add_gps(1,gps.get_latitude(),gps.get_longitude(),gps.get_altitude())
    lora.send(bytes(frame.bytes()))
    sleep(2)
    print("loop")



lora.close()
Esempio n. 7
0
def to_cayenne_lpp(dataframe: DataFrame):
    """
    Serialize dataframe to binary CayenneLPP format.

    :param dataframe:
    """

    from cayennelpp import LppFrame
    frame = LppFrame()

    channel = {}
    channel['temp'] = 0
    channel['ana_out'] = 0
    channel['hum'] = 0
    channel['press'] = 0
    channel['scale'] = 0

    # TODO: Iterate ``dataframe.readings`` to get more metadata from sensor configuration.
    # It is a list of ``SensorReading`` instances, each having a ``sensor`` and ``data`` attribute.

    for key, value in dataframe.data_out.items():

        #log.debug('-' * 42)

        # TODO: Maybe implement different naming conventions.
        name = key.split("_")[0]
        # try:
        #     channel = int(key.split(":")[1])
        # except IndexError:
        #     channel = 0

        if "temperature" in name:
            frame.add_temperature(channel['temp'], value)
            channel['temp'] += 1
        elif "voltage" in name:
            frame.add_analog_output(channel['ana_out'], value)
            channel['ana_out'] += 1
        elif "humidity" in name:
            frame.add_humidity(channel['hum'], value)
            channel['hum'] += 1
        elif "pressure" in name:
            frame.add_barometer(channel['press'], value)
            channel['press'] += 1
        elif "weight" in name:
            frame.add_analog_input(channel['scale'], value)
            channel['scale'] += 1
        elif "analog-output" in name:
            frame.add_analog_output(channel, value)
        elif "analog-input" in name:
            frame.add_analog_input(channel, value)
        elif "digital-input" in name:
            frame.add_digital_input(channel, value)
        elif "digital_output" in name:
            frame.add_digital_output(channel, value)
        elif "illuminance" in name:
            frame.add_luminosity(channel, value)
        elif "barometer" in name:
            frame.add_barometer(channel, value)
        elif "presence" in name:
            frame.add_presence(channel, value)
        elif "accelerometer" in name:
            frame.add_accelerometer(channel, value)
        elif "gyrometer" in name:
            frame.add_gyrometer(channel, value)
        elif "gps" in name:
            frame.add_gps(channel, value)

        # TODO: Fork cayenneLPP and implement load cell telemetry.
        # TODO: Add load encoder as ID 122 (3322)
        # http://openmobilealliance.org/wp/OMNA/LwM2M/LwM2MRegistry.html#extlabel
        # http://www.openmobilealliance.org/tech/profiles/lwm2m/3322.xml

        # elif False and "load" in name:
        #     frame.add_load(channel, value)

        # TODO: Map memfree and other baseline sensors appropriately.

        else:
            # TODO: raise Exception here?
            log.info(
                '[CayenneLPP] Sensor type "{}" not found in CayenneLPP'.format(
                    name))

    return frame.bytes()
Esempio n. 8
0
def test_uplink_environmental_sensors(mocker, network_lora, caplog):
    """
    Pretend to invoke the datalogger on a LoPy4 with environmental sensors.

    By intercepting the lora socket communication, proof that the
    submitted payload is correct by checking the raw payload value
    and decoding it through Cayenne.
    """

    # Define artificial LoRa conversation.
    network_lora.register_conversation()

    # Mix together different settings.
    from test.settings import telemetry_lorawan
    from test.settings import sensors as sensor_settings
    mocker.patch('test.settings.telemetry_lorawan.sensors',
                 sensor_settings.sensors)

    # Invoke datalogger with LoRaWAN telemetry settings for a single duty cycle.
    invoke_datalogger_pycom(caplog, settings=telemetry_lorawan)

    # Capture log output.
    captured = caplog.text

    # Proof it works by verifying log output.
    assert "Starting Terkin datalogger" in captured, captured
    assert "platform: LoPy4" in captured, captured
    assert "[LoRa] Starting LoRa Manager" in captured, captured
    assert "Telemetry transport: CayenneLPP over LoRaWAN/TTN" in captured, captured
    assert "Telemetry status: SUCCESS (1/1)" in captured, captured

    # Check the raw LoRa payload.
    from mocket import Mocket
    assert Mocket.last_request() == bytearray(
        b'\x00g\x01\xbf\x00\x03\x01\xa4\x00\x02\x01\x80\x01g\x01\xe1\x02g\x01\xe1'
        b'\x03g\x00\x97\x00s)7\x00h\x9b\x00\x01\x00')

    # Check the value after decoding from CayenneLPP.
    from cayennelpp import LppFrame
    data = LppFrame.from_bytes(Mocket.last_request()).data

    # System temperature
    assert data[0].channel == 0
    assert data[0].type == 103
    assert data[0].value == (44.7, )

    # Voltage
    assert data[1].channel == 0
    assert data[1].type == 3
    assert data[1].value == (4.2, )

    # Weight (kg)
    assert data[2].channel == 0
    assert data[2].type == 2
    assert data[2].value == (3.84, )

    # DS18B20 temperature
    assert data[3].channel == 1
    assert data[3].type == 103
    assert data[3].value == (48.1, )
    assert data[4].channel == 2
    assert data[4].type == 103
    assert data[4].value == (48.1, )

    # BME280 temperature
    assert data[5].channel == 3
    assert data[5].type == 103
    assert data[5].value == (15.1, )

    # BME280 pressure
    assert data[6].channel == 0
    assert data[6].type == 115
    assert data[6].value == (1055.1, )

    # BME280 humidity
    assert data[7].channel == 0
    assert data[7].type == 104
    assert data[7].value == (77.5, )

    # EOF?
    assert data[8].channel == 0
    assert data[8].type == 1
    assert data[8].value == (0, )

    assert "[LoRa] No downlink message processed" in captured, captured
Esempio n. 9
0
print("APP_KEY = ", str(APP_KEY))
lora.set_config(ch_mask='0,FF00')
lora.set_config(ch_mask='1,0000')
lora.set_config(ch_mask='2,0000')
lora.set_config(ch_mask='3,0000')
lora.set_config(ch_mask='4,0000')

print('Joining')
lora.join_otaa()
# Note that DR is different from SF and depends on the region
# See: https://docs.exploratory.engineering/lora/dr_sf/
# Set Data Rate to 5 which is SF7/125kHz for EU868
lora.dr = 3

# create empty frame
frame = LppFrame()
# add some sensor data
frame.add_temperature(0, -11.2)
frame.add_humidity(0, 30.5)
#frame.add_generic(0, 1)
# get byte buffer in CayenneLPP format
buffer = frame.bytes()
print(frame)
#print(bytes.fromhex('0102{:04x}'.format(randint(0, 0x7FFF))))
#print(frame.bytes())
print("hexlify")
print(bytes.fromhex(str(binascii.hexlify(frame.bytes()).decode())))
lora.send(bytes.fromhex(str(binascii.hexlify(frame.bytes()).decode())))
#print(str(frame.bytes()))
#lora.send(bytes.fromhex(binascii.hexlify(frame.bytes()) ), port=11, confirm=True)
print('DR', lora.dr)
Esempio n. 10
0
lora.set_config(ch_mask = '0,FF00')
lora.set_config(ch_mask = '1,0000')
lora.set_config(ch_mask = '2,0000')
lora.set_config(ch_mask = '3,0000')
lora.set_config(ch_mask = '4,0000')

print('Joining')
lora.join_otaa()
# Note that DR is different from SF and depends on the region
# See: https://docs.exploratory.engineering/lora/dr_sf/
# Set Data Rate to 5 which is SF7/125kHz for EU868
lora.dr = 0

# create empty frame
frame = LppFrame()
# add some sensor data
frame.add_temperature(0, -11.2)
frame.add_humidity(0, 30.5)
#frame.add_generic(0, 1)
# get byte buffer in CayenneLPP format
buffer = frame.bytes()
print(frame)
#print(bytes.fromhex('0102{:04x}'.format(randint(0, 0x7FFF))))
#print(frame.bytes())
print("hexlify")
print(bytes.fromhex(str(binascii.hexlify(frame.bytes()).decode())))
lora.send(bytes.fromhex(str(binascii.hexlify(frame.bytes()).decode() )))
#print(str(frame.bytes()))
#lora.send(bytes.fromhex(binascii.hexlify(frame.bytes()) ), port=11, confirm=True)
print('DR', lora.dr)
Esempio n. 11
0
def to_cayenne_lpp(data):
    """
    Serialize plain data dictionary to binary CayenneLPP format.
    """

    from cayennelpp import LppFrame
    frame = LppFrame()

    for key, value in data.items():

        # TODO: Maybe implement different naming conventions.
        name = key.split("_")[0]
        try:
            channel = int(key.split("_")[1])
        except IndexError:
            channel = 0

        if "temperature" in name:
            frame.add_temperature(channel, value)
        elif "digital-input" in name:
            frame.add_digital_input(channel, value)
        elif "digital_output" in name:
            frame.add_digital_output(channel, value)
        elif "analog-input" in name:
            frame.add_analog_input(channel, value)
        elif "analog-output" in name:
            frame.add_analog_output(channel, value)
        elif "illuminance" in name:
            frame.add_illuminance(channel, value)
        elif "presence" in name:
            frame.add_presence(channel, value)
        elif "humidity" in name:
            frame.add_humidity(channel, value)
        elif "accelerometer" in name:
            frame.add_accelerometer(channel, value)
        elif "barometer" in name:
            frame.add_barometer(channel, value)
        elif "gyrometer" in name:
            frame.add_gyrometer(channel, value)
        elif "gps" in name:
            frame.add_gps(channel, value)

        # TODO: Fork cayenneLPP and implement load cell telemetry.
        # TODO: Add load encoder as ID 122 (3322)
        # http://openmobilealliance.org/wp/OMNA/LwM2M/LwM2MRegistry.html#extlabel
        # http://www.openmobilealliance.org/tech/profiles/lwm2m/3322.xml
        elif False and "load" in name:
            frame.add_load(channel, value)

        # TODO: Map memfree and other baseline sensors appropriately.

        else:
            # TODO: raise Exception here?
            log.info(
                '[CayenneLPP] Sensor type "{}" not found in CayenneLPP'.format(
                    name))

    return frame.bytes()
Esempio n. 12
0
def to_cayenne_lpp_hiveeyes(dataframe: DataFrame):
    """
    Serialize dataframe to binary CayenneLPP format.

    :param dataframe:
    """

    from cayennelpp import LppFrame
    frame = LppFrame()

    channel = {}
    channel['temp']   = 10
    channel['volt']   = 2
    channel['pres']   = 1
    channel['scal']   = 6

    # TODO: Iterate ``dataframe.readings`` to get more metadata from sensor configuration.
    # It is a list of ``SensorReading`` instances, each having a ``sensor`` and ``data`` attribute.

    # log.info('dataframe.data_out.items : %s', dataframe.data_out.items())

    for key, value in dataframe.data_out.items():

        #log.debug('-' * 42)

        # TODO: Maybe implement different naming conventions.
        name = key.split("_")[0]
        #     channel = 0

        if "system" in name:
            if "voltage" in name:
                # treat voltage as system sensors
                # put battery voltage to channel 0
                # put solar voltage to channel 1
                # put other voltages to channel 2++
                if "battery" in name:
                    chan = 0
                elif "solar" in name:
                    chan = 1
                else:
                    chan = channel['volt']
                    channel['volt'] += 1
                frame.add_voltage(chan, value)
            elif "temperature" in name:
                frame.add_temperature(0, value)
        elif "i2c" in name:
            # assume BME280 on I2C bus as outside sensor and assign the variables to channel 5
            if "temperature" in name:
                frame.add_temperature(5, value)
            elif "humidity" in name:
                frame.add_humidity(5, value)
            elif "pressure" in name:
                frame.add_barometer(5, value)
        elif "weight" in name:
            # treat weight as outside sensor and assign to channel 5-9
            # Channel 5 for single reading (weight.0))
            # Channel 6-9 for multiple readings (weight.[1-4])
            if name == "weight.0":
                chan = 5
            else:
                chan = channel['scal']
                channel['scal'] += 1
            frame.add_load(chan, value)
        elif "onewire" in name:
            # assume DS18B20 as inside sensors and assign to channel 10++
            if "temperature" in name:
                frame.add_temperature(channel['temp'], value)
                channel['temp'] += 1
        elif "analog-output" in name:
            frame.add_analog_output(channel, value)
        elif "analog-input" in name:
            frame.add_analog_input(channel, value)
        elif "digital-input" in name:
            frame.add_digital_input(channel, value)
        elif "digital_output" in name:
            frame.add_digital_output(channel, value)
        elif "illuminance" in name:
            frame.add_luminosity(channel, value)
        elif "barometer" in name:
            frame.add_barometer(channel, value)
        elif "presence" in name:
            frame.add_presence(channel, value)
        elif "accelerometer" in name:
            frame.add_accelerometer(channel, value)
        elif "gyrometer" in name:
            frame.add_gyrometer(channel, value)
        #elif "gps" in name:
        #    frame.add_gps(channel, value)


        # TODO: Fork cayenneLPP and implement load cell telemetry.
        # TODO: Add load encoder as ID 122 (3322)
        # http://openmobilealliance.org/wp/OMNA/LwM2M/LwM2MRegistry.html#extlabel
        # http://www.openmobilealliance.org/tech/profiles/lwm2m/3322.xml

        # elif False and "load" in name:
        #     frame.add_load(channel, value)

        # TODO: Map memfree and other baseline sensors appropriately.

        else:
            # TODO: raise Exception here?
            log.info('[CayenneLPP] Sensor type "{}" not found in CayenneLPP'.format(name))

    return frame.bytes()
Esempio n. 13
0
def to_cayenne_lpp_ratrack(dataframe: DataFrame):
    """
    Serialize dataframe to binary CayenneLPP format.

    :param dataframe:
    """

    from cayennelpp import LppFrame
    frame = LppFrame()

    channel = {}
    channel['temp']   = 10

    if ('alt' or 'altitude') and ('lat' or 'longitude') and ('lon' or 'longitude') in dataframe.data_out.keys():
        log.info('GOT GPS!')
        frame.add_gps(0, dataframe.data_out.get('lat'), dataframe.data_out.get('lon'), dataframe.data_out.get('alt'))

    if 'batterie_volt' in dataframe.data_out.keys():
        frame.add_analog_input(14, dataframe.data_out.get('batterie_volt'))

    for key, value in dataframe.data_out.items():

        name = key

        if "system" in name:
            pass
        elif "i2c" in name:
            # assume BME280 on I2C bus as outside sensor and assign the variables to channel 5
            if "temperature" in name:
                frame.add_temperature(5, value)
            elif "humidity" in name:
                frame.add_humidity(5, value)
            elif "pressure" in name:
                frame.add_barometer(5, value)
        elif "onewire" in name:
            # assume DS18B20 as inside sensors and assign to channel 10++
            if "temperature" in name:
                frame.add_temperature(channel['temp'], value)
                channel['temp'] += 1
        else:
            # TODO: raise Exception here?
            #log.info('[CayenneLPP] Sensor type "{}" not found in CayenneLPP'.format(name))
            hu1 = 2

    return frame.bytes()
Esempio n. 14
0
from cayennelpp import LppFrame

# byte buffer in CayenneLPP format with 1 data item
# i.e. on channel 1, with a temperature of 25.5C
buffer = bytearray(
    [0x01, 0x02, 0x01, 0xa8, 0x03, 0x68, 0x07, 0x05, 0x67, 0xfe, 0x5b])
# create frame from bytes
frame = LppFrame().from_bytes(buffer)
# print the frame and its data
print(frame)