Giter Site home page Giter Site logo

electroniccats / cayennelpp Goto Github PK

View Code? Open in Web Editor NEW
104.0 13.0 48.0 132 KB

Library for Arduino compatible with Cayenne Low Power Payload

Home Page: http://electroniccats.com/

License: MIT License

C++ 93.20% JavaScript 6.41% CMake 0.39%
arduino arduino-library cayennelpp lorawan cayenne-low-power-payload lora

cayennelpp's Introduction

CayenneLPP by Electronic Cats - Library for Arduino

LibraryBuild

This is an Arduino Library for Arduino Compatible with Cayenne Low Power Payload with Extended Data Types.

CayenneLPP is a format designed by myDevices to integrate LoRaWan nodes into their IoT Platform. It is used to send sensor data in a packed way to The Things Network platform. You can read more on myDevices CayenneLPP

Description

CayenneLPP format is a quite well-optimized way to send sensor data over low bit rate connection, like LoRa. You may find, probably, a better way for your specific project but CayenneLPP is a standardized and proven format that packs data in a sufficient way. It implements basic sensor types specified by OMA SpecWorks, formerly IPSO Alliance.

It supports multichannel data, which means that you can use it on multisensor devices.

Warning

This version of the library includes several IPSO data types not included in the original work by Johan Stokking or most of the forks and side works by other people, these additional data types are not supported by myDevices Cayenne. In addition, it includes a fully backward-compatible decoder in JavaScript, suitable for implementations with NodeRED or TTN, for instance.

When using the decoder, you must install the ArduinoJson 6.X library. You can find it in both the Arduino IDE and PlatformIO library managers.

How to contribute

Contributions are welcome!

Please read the document Contribution Manual which will show you how to contribute your changes to the project.

✨ Thanks to all our contributors! ✨

See Electronic Cats CLA for more information.

See the community code of conduct for a vision of the community we want to build and what we expect from it.

References

Maintainer

Electronic Cats invests time and resources in providing this open-source design design, please support Electronic Cats and open-source hardware by purchasing products from Electronic Cats!

License

Based on the work of Johan Stokking.

The MIT License (MIT)

cayennelpp's People

Contributors

aparcar avatar asanchezdelc avatar eric286 avatar ivanamg avatar jazhe avatar marcelol52 avatar mincequi avatar oscar-raygoza avatar per1234 avatar ricaun avatar sabas1080 avatar schrein avatar teaalltr avatar thiasb avatar xoseperez avatar xpeqex avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cayennelpp's Issues

Add pH sensor data type to the library

Hi,

Helping a Scout work on his Eagle project to read temp and pH at a public golf courses irrigation ponds. I am trying to figure out how to add the data type to the CayenneLPP Arduino library. This documentation was kinda helpful, but doesn't speak exactly to what I need to do.

Looking for guidance on how to add a data type without breaking the library.

Thanks!

Decoding in Arduino

Hello, and thanks for this very useful library.
Is there any plan to add decoding in this library? This would be useful for downlink/actuation.

nullptr issue with latest ArduinoJson

In one of the latest ArduinoJson versions a nullptr check was added, which now crashes with CayenneLPP...

Ref: https://github.com/bblanchon/ArduinoJson/releases/tag/v6.17.0

Building in release mode
Compiling .pio/build/cubecell_board/src/main.cpp.o
Compiling .pio/build/cubecell_board/lib4ee/CayenneLPP/CayenneLPP.cpp.o
Compiling .pio/build/cubecell_board/libc02/LoraWan102/loramac/region/RegionEU433.c.o
Compiling .pio/build/cubecell_board/libc02/LoraWan102/loramac/region/RegionEU868.c.o
In file included from .pio/libdeps/cubecell_board/ArduinoJson/src/ArduinoJson.hpp:7,
                 from .pio/libdeps/cubecell_board/ArduinoJson/src/ArduinoJson.h:9,
                 from src/main.cpp:2:
.pio/libdeps/cubecell_board/ArduinoJson/src/ArduinoJson/Configuration.hpp:271:4: error: #error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
  271 | #  error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
      |    ^~~~~
Compiling .pio/build/cubecell_board/libc02/LoraWan102/loramac/region/RegionIN865.c.o
Compiling .pio/build/cubecell_board/libc02/LoraWan102/loramac/region/RegionKR920.c.o
Compiling .pio/build/cubecell_board/libc02/LoraWan102/loramac/region/RegionUS915-Hybrid.c.o
Compiling .pio/build/cubecell_board/libc02/LoraWan102/loramac/region/RegionUS915.c.o
In file included from .pio/libdeps/cubecell_board/ArduinoJson/src/ArduinoJson.hpp:7,
                 from .pio/libdeps/cubecell_board/ArduinoJson/src/ArduinoJson.h:9,
                 from .pio/libdeps/cubecell_board/CayenneLPP/src/CayenneLPP.h:11,
                 from .pio/libdeps/cubecell_board/CayenneLPP/src/CayenneLPP.cpp:6:
.pio/libdeps/cubecell_board/ArduinoJson/src/ArduinoJson/Configuration.hpp:271:4: error: #error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
  271 | #  error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
      |    ^~~~~
Compiling .pio/build/cubecell_board/libc02/LoraWan102/radio/radio.c.o
*** [.pio/build/cubecell_board/src/main.cpp.o] Error 1
*** [.pio/build/cubecell_board/lib4ee/CayenneLPP/CayenneLPP.cpp.o] Error 1

Payload arriving twice at Cayenne

Dear Github Team,

I am encountering some problems with the displaying of the sensor data. We are using Arduino IDE with this library:
https://github.com/ElectronicCats/CayenneLPP
version 1.0.2 (1.0.3 has been released a couple of days).

We transmit the following parameters:
lpp.addTemperature(1, Temperature0);
lpp.addTemperature(2, Temperature1);
lpp.addTemperature(3, Temperature2);
lpp.addAnalogInput(4, moisture);
lpp.addAnalogInput(5, batteryLevel);

As you can see from the attached .png, the parameters arrive multiple times and the values are also different. Have you seen clients with these problems?
ground_sensor

Best regards and thank you,
Marco

Add isEmpty()

It would be really useful to introduce an isEmpty function to lpp.
As an example, you may want to check a global lpp for an "empty" or "non-empty" state before sending a packet.

Cayenne decode some payploads

Hi, I am confused with this, I run the code 1 on my Wireless Stick Lite from Heltec and when I decode with CayenneLPP on ttn everything works fine, but then I do just one modification (code 2) and set other value to send and try to decode the payload the output is invalid on ttn.

What’s wrong with my code? I’m a beginner with Cayenne and ttn but I would think that the codes are almost the same

Code 1:
`#include <Arduino.h>
#include <CayenneLPP.h>

CayenneLPP lpp(51);

void setup() {
Serial.begin(115200);
}

void loop() {
lpp.reset();
lpp.addTemperature(7, 26.5f);
lpp.addRelativeHumidity(8, 86.6f);

uint8_t *payload = lpp.getBuffer();

char buffer[7];
String payloadString;

for (int i = 0; i < lpp.getSize(); i++) {
sprintf(buffer, "%02x", payload[i]);
payloadString += buffer;
}

Serial.print("HEX: ");
Serial.print(payloadString);
Serial.print(" | SIZE: ");
Serial.println(payloadString.length());

delay(5000);
}`

Code 2:
`#include <Arduino.h>
#include <CayenneLPP.h>

CayenneLPP lpp(51);

void setup() {
Serial.begin(115200);
}

void loop() {
lpp.reset();
lpp.addVoltage(1,3.2f);

uint8_t *payload = lpp.getBuffer();

char buffer[7];
String payloadString;

for (int i = 0; i < lpp.getSize(); i++) {
sprintf(buffer, "%02x", payload[i]);
payloadString += buffer;
}

Serial.print("HEX: ");
Serial.print(payloadString);
Serial.print(" | SIZE: ");
Serial.println(payloadString.length());

delay(5000);
}`

The output for code 1 is HEX: 076701090868ad and for code 2 HEX: 01740140

I also test with .addGenericSensor() and .addSwitch(), and the ttn output decoded is the same

GPS: add support for precision data

Sometimes you need to know how accurate a GPS lock is, so it would be nice to have additional (optional) info for the gps signal

e.g TTNMapper:
The JSON object should contain the keys "latitude", "longitude" and "altitude" and one of "hdop", "accuracy" or "sats". When using the Cayenne LPP data format, the GPS coordinates will be decoded into a different JSON format, but this format is also supported. Cayenne LPP does not contain a GPS accuracy, and therefore this data will be considered as inferior and will carry less weight in calculation of coverage, and will be deleted first during data cleanup.

hdop: decimal values up to 50 (float)
accuracy: ? this one i didnt get. in m? in %?
sats: up to 12 sattelites (Global Positioning System Fix Data (GGA) NN ) can be in sight. so int should do

Enhance frequency from int to float and have 2 digits transmitted

hi,

i stumbled over an another unaccuracy.

atm frequency is an int

uint8_t addFrequency(uint8_t channel, uint32_t value); // in hertzs

may i ask for which cases this value is usable?

i do some reseach in the energy sector and for this purpose its VERY important to know the exact electrical energy grid frequency. alt least 1 digit will do but 2 digits would be much better.

the cause is that the electrical grid is frequency controlled and actions MUST be taken when +/-0.1hz happen.
sorry, but i dont find the adequate articles in the english wiki, only a german explaination.

for this the Frequency value must be changed to a float value.

Polyline support

Hi,
i created a fork of this project to support polylines (a set of GPS coordinates). This is loosely inspired by googles polylines: https://developers.google.com/maps/documentation/utilities/polylinealgorithm

Unfortunately, there is no definition from IPSO for polylines, so I just went ahead and defined/wrote it myself.

So, my question is: are you willing to support data types that are NOT defined by IPSO and if yes,
which number shall i assign this to (maybe start at 240? (as it is TBC from IPSO), or 151? (GSM types), or 187? (OpenAIS types)).

Short summery about my implementation (will create a PR for review):
my impl can encode a set of GPS coordinates (e.g. a Route) very efficiently through delta compression. So, i encode a single GPS coordinate with 6 bytes (3 byte for lat/long each) and then pack the deltas for next coordinate in a single byte (4 bit for lat/long each).
Another aspoect is, that my payload will have a dynamic size, so the first byte after channel and type is indicating the length of the polyline.

Please, tell me what you think :)

Enhancement: "businesslike conduct" round to reduce data error from 0.09 to 0.05 (~50% accuracy enhancement)

hi,

we have seen some problems when it comes to rounding (in our case for temp measurements).

in the current code the float temp just gets cut after the 1st decimal place, which is very inaccurate!

uint32_t v = value * multiplier;

in this case the error is at worst 0.09. so almost 0.1° off.

instead the float temp should be businesslike conduct rounded (in germany we call this "Kaufmännisches Runden") before chopping off the last digit, like so:

uint32_t v = round(value * multiplier);

in this case the error is @ max. 0.05° off. which is much more accurate for professional use. of cause other values can benefit from this kind of correction, too.

Some protocol improvements

Hi again,

since i am dealing with CayenneLPP quite a bit, i see some serious downsides:
any Change/Extension for another IPSO Object/Property will render any decoder that does not understand the changes unusable.
If the appropriate decoder does not know about each single object that had been sent, i will fail, since it also does not know about the size of the unsupported object.

To circumvent this, i have a suggestion (among others) to improve this protocol:

  1. Do we need 256 Channels? Otherwise, we could limit that to 16 Channels and use other 4 bit for size information. I was thinking about this: 0 - 11 encodes the size if the data object directly. 12 could mean boolean false, 13 boolean true, 14 flags (a flag byte will follow after the type byte, see BIPSO spec), 15 size (a size byte will follow after the type byte). For flags we might define a fixed size for values (e.g. 16 bit value) so the decoder knows how far it shall advance within the byte buffer, if the appropriate object is not understood.
  2. To support extended/more types we could reserve types values starting from 240 (or 248) to indicate, that an extType byte will follow after the type byte (or the size/flags byte if indicated). This would allow another 16 * 256 types (or 8 * 256).

These two changes would perfectly allow anything that comes up in the future and also allows encoders to be backwards compatible with previous protocol versions.
Additionally, boolean data can be encoded directly without spending another byte.
The downside: we would be limited to 16 channels (which is probably enough) if not adding another byte to the payload.

What do you think?

Add support for power measurement type (IPSO: 3305)

Hi,
as i need support for a smart meter device, i was wondering if it is desired to support the power measurement type (IPSO:: 3305). Resulting in type 105 for CayenneLPP.
Reasons to support this:

  • support negative consumption (energy export)
  • Provide min/max values
  • Provide range
    Alternatively, we could use IPSO Type 3421, which might fit even better (due to energy im- and export).

I would orient myself to the BIPSO specification and also support some optional values:
https://github.com/bluetoother/bipso/wiki/BIPSO-Specification

What i also would add is support for SFLOAT16 data type (from bluetooth specification). The advantages of this type are:

  • high dynamic range
  • takes little space (16 vs 32-bit float)
  • better support for human readable values (exponent uses base 10 (instead base 2)).

For my intended design, the payload would look like this:

  • 1x uint8 for flags (see BIPSO spec)
  • 1x sfloat16: Instantaneous active power: Watts (mandatory): positive for export, negative for import
  • 1x sfloat16: Min Measured active power: Watts (optional)
  • 1x sfloat16: Max Measured active power: Watts (optional)
  • 1x sfloat16: Min Range active power: Watts (optional)
  • 1x sfloat16: Max Range active power: Watts (optional)
  • 1x sfloat16: Cumulative active power export: Wh (optional)
  • 1x sfloat16: Cumulative active power import: Wh (optional)

Please share your thoughts. I am also willing to provide a PR.

Thanks a lot :)

Feature Request: Be able to change feed name

CayenneLPP seems to force the feed name. Can the feed name be changed in the sketch?

example

lpp.addDigitalInput(1, 0);

creates an MQTT feed called Digital_Input

Can that feed name be edited before it is sent?

Adding new data types

I've been working on a fork of this repo to add new data types for:

  • Generic Sensor
  • Voltage
  • Current
  • Frequency
  • Percentage
  • Altitude
  • Power
  • Distance
  • Energy
  • Direction
  • Switch

I have also added a unit test suite based on AUnit and a backwards compatible javascript decoder for TTN or NodeRED.

Everything is in the forked repo: https://github.com/xoseperez/CayenneLPP

The problem is that the code base is very different, including some files moved to subfolders to suit PlatformIO. The class itself is backwards compatible with this repo thou. My question is: should I keep it as a separate repo or would you be willing to accept a PR with the changes?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.