Azure / iotedge-lorawan-starterkit

Sample implementation of LoRaWAN components to connect LoRaWAN antenna gateway running IoT Edge directly with Azure IoT.
https://azure.github.io/iotedge-lorawan-starterkit/2.2.1
Other
184 stars 63 forks source link

Encoder-decoder for STREGA devices #247

Closed donniekerr closed 3 years ago

donniekerr commented 4 years ago

The Strega Smart Valve sent me this link https://github.com/Strega-Technologies/Strega It is Javascript.

Does that mean I need to go through this custom setup? https://github.com/Azure/iotedge-lorawan-starterkit/blob/dev/Samples/DecoderSample/ReadMe.md

Or do I need your help since it is a different language?

Mandur commented 4 years ago

Hello,

Correct, this tutorial explain how to write a custom decoder. If you want to deploy it on the device Edge, you should implement an iot edge module with this decoder. Here is iot edge node documentation For dev/test, note that you could set the SensorDecoder twin to be a public URL and it should just work, so you could just have a local web api that could do the decoding for you.

Best regards,

Mikhail

gerfen commented 4 years ago

I've already written a decoder for Strega valves in C#. It's fairly trivial:

public class SmartValveDecoder
    {
        public static string Decode(string devEui, byte[] payload, uint fport)
        {
            var hex = BitConverter.ToString(payload);
            var hexValues = hex.Split('-').Select(x=>(Convert.ToInt16(x)-30).ToString()).ToArray();
            return JsonConvert.SerializeObject(DecodePeriodicUplink(hexValues, payload));
        }

        private static Dictionary<string, object> DecodePeriodicUplink(string[] hexValues, byte[] payload)
        {
            var dictionary = new Dictionary<string, object>
            {
                { "battery", Convert.ToInt32($"{hexValues[0]}{hexValues[1]}{hexValues[2]}{hexValues[3]}")},
                { "enclosureIsOpen",  IsBitSet(hexValues[4], 0X0002) },
                { "valveIsOpen",  IsBitSet(hexValues[4], 0X0001) }
            };
            return dictionary;
        }

        private static bool IsBitSet(string value, int checkBit)
        {
            return IsBitSet(Convert.ToInt32(value), checkBit);
        }

        private static bool IsBitSet(int value, int checkBit)
        {
            return (value & checkBit) == checkBit;
        }
    }
donniekerr commented 4 years ago

Very cool @gerfen . Thanks. What about sending command to open/close the value? I assume it also has to run though this custom module too for encoding a json object sent from the edge or the cloud. Do you have to build a separate encoder module or do you do encoding/decoding in the same module? It is a key requirement for me ASA ML job to be able to open/close the value on command.

gerfen commented 4 years ago

You need to send a CloudToDevice message to the valve.

  public class CloudToDeviceMessageProxy : ICloudToDeviceMessageProxy
    {
        private readonly ServiceClient serviceClient_;
        public CloudToDeviceMessageProxy(string iotHubConnectionString)
        {
            serviceClient_ = ServiceClient.CreateFromConnectionString(iotHubConnectionString);
        }

        public async Task SendMessageAsync<T>(string deviceId, T message)
        {
            var json = JsonConvert.SerializeObject(message);
            var bytes = Encoding.UTF8.GetBytes(json);
            var cloudToDeviceMessage = new Message(bytes)
            {
                Ack = DeliveryAcknowledgement.Full,
                MessageId = Guid.NewGuid().ToString()
            };

            await serviceClient_.SendAsync(deviceId, cloudToDeviceMessage);
        }
    }

Then call it like this...

await cloudToDeviceMessageProxy_.SendMessageAsync(deviceId, new DeviceMessage { Data = request.State ? "1" : "0", Port = 1 }

where "deviceId" is the DeviceEUI.

I have a .Net Core WebAPI in place to do this. You could do this in an Azure function if you want something less heavy weight.

UPDATE: If you want to do it at the edge, you'll need to look at the code which receives the CloudToDevice messages to replicate sending the message to the device.

donniekerr commented 4 years ago

Cool. I have an IoT Hub Event that calls an Azure Function in Node like this https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-node-node-c2d#send-a-cloud-to-device-message . I just wasn't sure if it had to be encoded using the Strega encoder example they sent.
Thanks! Donnie

donniekerr commented 4 years ago

@gerfen Know why I get this error? I'm not a .Net guy :) I simply dropped your smart valve code in and built the module just to learn how to do it.

/build/Samples/DecoderSample/SensorDecoderModule.csproj : warning NU1701: Package 'System.Runtime.InteropServices 4.3.0' was restored using '.NETFramework,Version=v4.6.1' instead of the project target framework '.NETCoreApp,Version=v2.1'. This package may not be fully compatible with your project. Classes/LoraDecoders.cs(18,48): error CS1061: 'string[]' does not contain a definition for 'Select' and no accessible extension method 'Select' accepting a first argument of type 'string[]' could be found (are you missing a using directive or an assembly reference?) [/build/Samples/DecoderSample/SensorDecoderModule.csproj] The command '/bin/sh -c dotnet publish -c Release -o out' returned a non-zero code: 1

gerfen commented 4 years ago

I don't. Check your using statements?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;

@mandur Could this related to the update to .Net Core 3.1?

donniekerr commented 4 years ago

it was missing Linq . Thanks. Got the module set.

donniekerr commented 4 years ago

Should the decoder module show "running" ... before it is assigned to a device twin and an actual device is connected? I would expect the module to not change the to 406 when it is added. Or will it all magically run when the real device is connected/provisioned and the pktforwarder is running? I used all lowercase in the name and everything built just fine without errors. Just want to verify that the module is running on the edge, but it never actually shows up in the sudo iotedge list .

Screen Shot 2020-07-21 at 11 21 37 PM
ronniesa commented 4 years ago

Yes the module should be running already. All deployed module are started by IoT Edge and kept running even if it crashes it gets restarted. Looking at the module log on your gateway or the log of edgeagent can give you some insight what is wrong.

donniekerr commented 4 years ago

Finally back to re-solving this. I did see this error in the edgeAgent logs, so it explains why the decodevalve module wasn't installing. caused by: Could not pull image iotdockerregistry.azurecr.io/smartvalvedecoder:0.1-amd64 caused by: Get https://iotdockerregistry.azurecr.io/v2/smartvalvedecoder/manifests/0.1-amd64: unauthorized: Application not registered with AAD. I setup the Azure CR with the correct credentials and entered those into set modules in IoT Hub and it installs now. Thanks for the tip @ronniesa !

If you all don't mind, I'd like to keep this issue opened until my Gateway device arrives next week and I can deploy all these modules to it, instead of the Linux VM I'm testing with now. Then hopefully the PktFwd will work on it too!

Screen Shot 2020-08-04 at 1 39 07 PM
Mandur commented 4 years ago

Great, thank you @gerfen for the help . @donniekerr we are eagerly waiting for your updates!

donniekerr commented 4 years ago

Sidebar question: What is the minimum hardware required for a Lora node device to connect to this gateway? Something like this Adafruit Feather 32u4 RFM95 LoRa Radio- 868 or 915 MHz - RadioFruit https://www.adafruit.com/product/3078 ? What else is required for a production device?

I'm looking to learn how to build a custom Lora device. Anyone have any recommendations on production hardware or a prototype board configuration? I'm trying to learn how it is configured for prototyping vs production. I want to start with the bare bones min, smallest Lora Module board as possible and just start with connecting a simple temp sensor to it. I don't want one of those kits that have a bunch of stuff I don't need. Goal is smallest and very narrow board. but can have multiple sensors connected to it.

BTW, still waiting on AAEON to ship my gateway. They said it is like a custom order because of the Lora support/antenna so that is why it is slow.

gerfen commented 4 years ago

@donniekerr You might consider looking at the Meadow board from Wilderness Labs. It supports the full .Net framework (and soon .Net Core). Here's a link to a presentation from the recent DevCamp where Byrn Lewis talks about integrating various LoRa modules with the Meadow board.

donniekerr commented 4 years ago

Thanks @gerfen . I'll check it out.

To keep this forum post going on further :) If one makes their own lora device to use with their own gateway/iot-edge-lorawan-starterkit (not public Things), how do you get the required keys to register them in IoT Hub? As I understand it the keys are provided by "the manufacturer." But, in my case we are not a manufacturer yet. Not clear in the Lora-Alliance docs how this process works.

gerfen commented 4 years ago

Since you are essentially creating your own private LoraWan network, you should be able to generate your own unique DeviceEUI per device. Then you can specify a common set of AppEUI and AppKey to use for all of the devices. You'll just need to make sure the keys are of the correct length and format. Almost all of the commercial devices I use allow me to change the AppKey and AppEUI settings. The DeviceEUI tends to be hardcoded but some allow those to be changed as well. Just make sure when you register the keys in the IoT Hub that they are upper case - see #236 for the reason.

@ronniesa may have more insight.

donniekerr commented 4 years ago

Excellent that makes it easier. Thanks!

Mandur commented 4 years ago

We are using this node as part of our CI and general development. We used also this one. In the end, any node properly implementing the LoRa 1.0.3 spec should be compatible, I don't see additional requirements.

@gerfen got all the other questions correct, thank you!

ronniesa commented 4 years ago

@donniekerr Hi Donni, for rapid PoC like temp sensor this board that Mik suggested https://www.seeedstudio.com/Seeeduino-LoRaWAN-p-2780.html is good as it has a very clean lora modem with a nice high level lora Arduino library. It has grove sensor support so you have tons of sensors that are plug and play, no soldering or manual work, you can buy a kit to add on top https://www.seeedstudio.com/Grove-Starter-Kit-for-Arduino-p-1855.html and here all the sensors: https://www.seeedstudio.com/category/Grove-c-1003.html . Disadvantage it needs a lipo battery plugged in as the voltage regulator over USB is bad so without the lipo it reboots from time to time. Also the power management is buggy. Bottom-line great for PoC not good for production work.

There are tons of ESP32 boards that are small yet really powerful it requires soldering and the lora stack is more messy. Most of the ESP32 are using LMIC lora library is powerful but I find it harder to use. We use this ones: https://heltec.org/project/wifi-lora-32/, http://www.lilygo.cn/products.aspx?TypeId=50003&fid=t3:50003:3 and also adafruit lora boards like this one: https://www.adafruit.com/product/3078.

Some of them are not great in range, some are not great in power consumption etc. but so far we never encountered a compatibility problem. Are you familiar with Arduino development?